package com.zmj.sy.mom.srv.aps.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.stream.CollectorUtil;
import cn.hutool.core.util.NumberUtil;
import cn.idev.excel.FastExcel;
import cn.idev.excel.context.AnalysisContext;
import cn.idev.excel.metadata.data.ReadCellData;
import cn.idev.excel.read.listener.ReadListener;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.ChainWrappers;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.zmj.sy.mom.srv.aps.bean.bo.*;
import com.zmj.sy.mom.srv.aps.bean.dto.wms.MesPicking;
import com.zmj.sy.mom.srv.aps.bean.entity.base.*;
import com.zmj.sy.mom.srv.aps.bean.entity.mes.Part;
import com.zmj.sy.mom.srv.aps.bean.entity.mes.WorkDetailTask;
import com.zmj.sy.mom.srv.aps.bean.entity.order.*;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.*;
import com.zmj.sy.mom.srv.aps.bean.entity.third.HexagonPackagePush;
import com.zmj.sy.mom.srv.aps.bean.entity.third.SinoCamPushDrawing;
import com.zmj.sy.mom.srv.aps.bean.entity.third.SinoCamPushPlan;
import com.zmj.sy.mom.srv.aps.bean.entity.third.SinoCamReceiveNestPart;
import com.zmj.sy.mom.srv.aps.bean.vo.aps.ApsNestHexagonItemReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.apsbatch.ApsBatchListResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.*;
import com.zmj.sy.mom.srv.aps.bean.vo.importframe.ImportFrameOrderErpAppendReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.importframe.ImportFrameOrderMbdReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.importframe.ImportFrameOrderPubReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.nest.NestProPushHexReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.order.*;
import com.zmj.sy.mom.srv.aps.bean.vo.processchainitem.OrderPhaseEditReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.weekdayscheme.WeekdaySchemeTimeRangeResVo;
import com.zmj.sy.mom.srv.aps.config.ProjectConfig;
import com.zmj.sy.mom.srv.aps.config.StrategyConfig;
import com.zmj.sy.mom.srv.aps.feign.WmsLtkApiClient;
import com.zmj.sy.mom.srv.aps.mapper.*;
import com.zmj.sy.mom.srv.aps.utils.*;
import com.zmj.sy.mom.srv.aps.utils.nest.HexagonNestRule;
import com.zmj.sy.mom.srv.aps.utils.nest.NestRule;
import com.zmj.sy.mom.srv.mbd.api.api.MomSrvMbdApiClient;
import com.zmj.sy.mom.srv.mbd.api.bean.dto.mbdUpdata.TbSizeInfoDto;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.io.File;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@RequiredArgsConstructor
@Service
@Slf4j
public class OrderService {

    private final OrderMapper orderMapper;

    private final CustomerMapper customerMapper;

    private final OrderBomMapper orderBomMapper;

    private final OrderPhaseMapper orderPhaseMapper;

    private final ApsOrderMapper apsOrderMapper;

    private final ApsWorkOrderMapper apsWorkOrderMapper;

    private final ApsWorkDetailMapper apsWorkDetailMapper;

    private final ApsDetailWeekdayMapper apsDetailWeekdayMapper;

    private final GroupMapper groupMapper;

    private final ReverseOrderMapper reverseOrderMapper;

    private final ApsBatchMapper apsBatchMapper;
    private final StationMapper stationMapper;
    //    private final StationGroupMapper stationGroupMapper;
    private final ProjectConfig projectConfig;
    private final StationWeekdaySchemeMapper stationWeekdaySchemeMapper;
    private final StationWeekdayRuleMapper stationWeekdayRuleMapper;
    private final ShiftMapper shiftMapper;
    private final BreakPeriodMapper breakPeriodMapper;
    private final ImportMbdOrderMapper importMbdOrderMapper;
    private final ImportMbdBomInfoMapper importMbdBomInfoMapper;
    private final ImportMbdPartInfoMapper importMbdPartInfoMapper;
    private final ImportMbdProcessPlanMapper importMbdProcessPlanMapper;
    private final MbdBalanceRateMapper mbdBalanceRateMapper;
    private final ImportMbdOperationMapper importMbdOperationMapper;
    private final MbdBalanceRateItemMapper mbdBalanceRateItemMapper;
    private final ReverseDetailMapper reverseDetailMapper;
    private final ReverseTopMapper reverseTopMapper;
    private final ImportErpBomMapper importErpBomMapper;
    private final ImportErpOrderMapper importErpOrderMapper;
    private final PhaseMapper phaseMapper;
    private final SinoCamPushDrawingMapper sinoCamPushDrawingMapper;
    private final SinoCamPushPlanMapper sinoCamPushPlanMapper;
    private final SinoCamReceiveNestPartMapper sinoCamReceiveNestPartMapper;
    private final WorkDetailTaskMapper workDetailTaskMapper;
    private final PartMapper partMapper;
    private final NestPushDrawMapper nestPushDrawMapper;
    private final OrderPartMapper orderPartMapper;
    private final ImportMbdDxfMapper importMbdDxfMapper;
    private final MomSrvMbdApiClient momSrvMbdApiClient;
    private final StringRedisTemplate stringRedisTemplate;
    private final ObjectMapper jacksonObjectMapper;
    private final HexagonNestOldUtils hexagonNestOldUtils;
    private final PlateStandardMapper plateStandardMapper;
    private final ProcessChainMapper processChainMapper;

    private final ProcessChainItemMapper processChainItemMapper;
    private final ReverseOrderService reverseOrderService;

    private final PartUtilService partUtilService;
    private final PhaseGroupMapper phaseGroupMapper;
    private final HexagonPackagePushMapper hexagonPackagePushMapper;
    private final OrderAccessoriesMapper orderAccessoriesMapper;
    private final ImportErpMappingMapper importErpMappingMapper;

    private final StrategyConfig strategyConfig;
    private final ImportFrameOrderMapper importFrameOrderMapper;
    private final ImportFrameBomMapper importFrameBomMapper;
    private final ImportFramePhaseMapper importFramePhaseMapper;
    private final PhaseJobMapper phaseJobMapper;
    private final PhaseJobRefMapper phaseJobRefMapper;
    private final ImportErpWorkOrderMapper importErpWorkOrderMapper;
    private final ImportErpMaterMapper importErpMaterMapper;
    private final ImportErpWorkOrderDetailMapper importErpWorkOrderDetailMapper;
    private final WmsLtkApiClient wmsLtkApiClient;
    private final WmsService wmsService;
    private final HexagonNestRule hexagonNestRule;
    private final FactoryMapper factoryMapper;

    public BasePageResVo<OrderListResVo> list(OrderListReqVo reqVo) {
        LambdaQueryWrapper<Order> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StringUtils.hasText(reqVo.getOrderCode()), Order::getOrderCode, reqVo.getOrderCode());
        wrapper.like(StringUtils.hasText(reqVo.getConstructNo()), Order::getConstructNo, reqVo.getConstructNo());
        if (reqVo.getOrderType() == null) {
            wrapper.in(Order::getOrderType, 1, 3, 4, 6);
        } else {
            wrapper.eq(Order::getOrderType, reqVo.getOrderType());
        }
        wrapper.like(reqVo.getSerialCode() != null, Order::getSerialCode, reqVo.getSerialCode());
        wrapper.eq(reqVo.getOrderStatus() != null, Order::getOrderStatus, reqVo.getOrderStatus());
        wrapper.ge(reqVo.getOrderStatusGe() != null, Order::getOrderStatus, reqVo.getOrderStatusGe());
        wrapper.like(StringUtils.hasText(reqVo.getMaterCode()), Order::getMaterCode, reqVo.getMaterCode());
        wrapper.like(StringUtils.hasText(reqVo.getMaterName()), Order::getMaterName, reqVo.getMaterName());

        wrapper.like(reqVo.getOrderType() != null, Order::getOrderStatus, reqVo.getOrderStatus());
        wrapper.ge(reqVo.getStartDeliveryDate() != null, Order::getDeliveryDateTime, reqVo.getStartDeliveryDate());
        wrapper.le(reqVo.getEndDeliveryDate() != null, Order::getDeliveryDateTime, reqVo.getEndDeliveryDate());
        wrapper.ge(reqVo.getStartSyncDate() != null, Order::getCreateDateTime, reqVo.getStartSyncDate());
        wrapper.le(reqVo.getEndSyncDate() != null, Order::getCreateDateTime, reqVo.getEndSyncDate());

        wrapper.orderByDesc(Order::getCreateDateTime);
        Page<Order> orderPage = orderMapper.selectPage(reqVo.toPage(), wrapper);

        BasePageResVo<OrderListResVo> orderListResVoBasePageResVo = BasePageResVo.of(orderPage, OrderListResVo.class);
        List<Factory> lineList = factoryMapper.lambdaQuery().eq(Factory::getType, 2).list();
        Map<Integer, Factory> factoryMap = lineList.stream().collect(Collectors.toMap(BaseEntity::getId, e -> e));

        for (OrderListResVo datum : orderListResVoBasePageResVo.getData()) {
            datum.setConstructNo(datum.getConstructNo());
            datum.setDeliveryDate(datum.getDeliveryDateTime());
            datum.setFactoryCode("170");

            if(datum.getLineId() != null){
                Factory factory = factoryMap.get(datum.getLineId());
                if(factory != null){
                    datum.setLineName(factory.getName());
                }
            }
        }

        return orderListResVoBasePageResVo;
    }

    public BasePageResVo<OrderListResVo> planList(PlanOrderListReqVo reqVo) {
        LambdaQueryWrapper<Order> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StringUtils.hasText(reqVo.getOrderCode()), Order::getOrderCode, reqVo.getOrderCode());
        wrapper.like(StringUtils.hasText(reqVo.getConstructNo()), Order::getConstructNo, reqVo.getConstructNo());

        if (!ObjectUtils.isEmpty(reqVo.getOrderType())) {
            wrapper.eq(Order::getOrderType, reqVo.getOrderType());
        } else {
            wrapper.in(Order::getOrderType, 2, 5);
        }

        if (!ObjectUtils.isEmpty(reqVo.getOrderStatus())) {
            wrapper.eq(Order::getOrderStatus, reqVo.getOrderStatus());
        } else if (reqVo.getOrderStatus() != null && reqVo.getOrderStatus() == 3) {
            wrapper.in(Order::getOrderStatus, 3, 4, 5);
        } else {
            wrapper.in(Order::getOrderStatus, 2, 3, 4, 5);
        }

        wrapper.like(StringUtils.hasText(reqVo.getFrameType()), Order::getFrameType, reqVo.getFrameType());
        wrapper.eq(StringUtils.hasText(reqVo.getPlannedMonth()), Order::getPlannedMonth, reqVo.getPlannedMonth());
        wrapper.like(StringUtils.hasText(reqVo.getPlmId()), Order::getPlmId, reqVo.getPlmId());
        wrapper.like(reqVo.getSerialCode() != null, Order::getSerialCode, reqVo.getSerialCode());
        wrapper.like(StringUtils.hasText(reqVo.getMaterCode()), Order::getMaterCode, reqVo.getMaterCode());
        wrapper.like(StringUtils.hasText(reqVo.getMaterName()), Order::getMaterName, reqVo.getMaterName());
        if (StringUtils.hasText(reqVo.getSort())) {
            if (org.apache.commons.lang3.StringUtils.equals(reqVo.getSort(), "seq")) {
                if ("asc".equals(reqVo.getOrder())) {
                    wrapper.orderByAsc(Order::getSeq);
                } else {
                    wrapper.orderByDesc(Order::getSeq);
                }
            }
        } else {
            wrapper.orderByDesc(Order::getPlannedMonth);
            wrapper.orderByDesc(Order::getSeq);
        }

        Page<Order> orderPage = orderMapper.selectPage(reqVo.toPage(), wrapper);

        BasePageResVo<OrderListResVo> orderListResVoBasePageResVo = BasePageResVo.of(orderPage, OrderListResVo.class);
        for (OrderListResVo datum : orderListResVoBasePageResVo.getData()) {
            datum.setConstructNo(datum.getConstructNo());
            datum.setDeliveryDate(datum.getDeliveryDateTime());
            datum.setFactoryCode("170");
        }
        return orderListResVoBasePageResVo;
    }

    public List<PreOrderListResVo> preOrderList(BasePageResVo<OrderListResVo> page1) {
        // 创建返回 List 对象
        List<PreOrderListResVo> resVo = new ArrayList<>();
        // 取调用查询方法结果的 orderId
        List<Integer> orderIds = page1.getData().stream().map(OrderListResVo::getId).collect(Collectors.toList());
        if (CollUtil.isEmpty(orderIds)) {
            // 没查到订单
            return resVo;
        }
        // 查询订单的包次
        List<ApsOrder> apsOrderList = apsOrderMapper.lambdaQuery().in(ApsOrder::getOrderId, orderIds).list();
        Map<Integer, List<ApsOrder>> apsOrderListMap = apsOrderList.stream().collect(Collectors.groupingBy(ApsOrder::getOrderId));
        // 查推送计划结果
        List<SinoCamPushPlan> sinoCamPushPlanList = sinoCamPushPlanMapper.lambdaQuery().in(SinoCamPushPlan::getOrderId, orderIds).list();
        Map<Integer, List<SinoCamPushPlan>> sinoCamPushPlanListMap = sinoCamPushPlanList.stream().collect(Collectors.groupingBy(SinoCamPushPlan::getOrderId));
        // 获取需要切割的工序
        List<String> phaseCodeList = projectConfig.getCuttingProcess();
        // 查排产计划
        List<ApsWorkDetail> apsWorkDetailList = apsWorkDetailMapper.lambdaQuery().in(ApsWorkDetail::getOrderId, orderIds).in(ApsWorkDetail::getPhaseCode, phaseCodeList).list();
        Map<Integer, List<ApsWorkDetail>> apsWorkDetailListMap = apsWorkDetailList.stream().collect(Collectors.groupingBy(ApsWorkDetail::getOrderId));
        for (OrderListResVo datum : page1.getData()) {
            PreOrderListResVo vo = MkBeanUtils.copyProperties(datum, PreOrderListResVo.class);
            List<ApsOrder> apsOrderDatum = apsOrderListMap.getOrDefault(datum.getId(), new ArrayList<>());
            int pushSeq = 0;
            int totalSeq = 0;
            if (!ObjectUtils.isEmpty(apsOrderDatum)) {
                totalSeq = apsOrderDatum.size();
            }
            for (ApsOrder apsOrder : apsOrderDatum) {
                if (apsOrder.getOrderStatus() > 6) {
                    pushSeq = pushSeq + 1;
                }
            }
            vo.setPushSeq(pushSeq + "/" + totalSeq);

            List<ApsWorkDetail> apsWorkDetailDatum = apsWorkDetailListMap.get(datum.getId());
            List<SinoCamPushPlan> sinoCamPushPlanDatum = sinoCamPushPlanListMap.get(datum.getId());
            if (CollUtil.isEmpty(sinoCamPushPlanDatum)) {
                vo.setPushPart(1);
            } else {
                BigDecimal totalCount = apsWorkDetailDatum.stream().map(ApsWorkDetail::getTotalCount).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal pushCount = sinoCamPushPlanDatum.stream().map(SinoCamPushPlan::getPlanAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                if (!totalCount.equals(pushCount)) {
                    vo.setPushPart(2);
                } else {
                    if (sinoCamPushPlanDatum.stream().allMatch(item -> item.getStatus() == 4)) {
                        vo.setPushPart(3);
                    } else if (sinoCamPushPlanDatum.stream().anyMatch(item -> item.getStatus() == 5)) {
                        vo.setPushPart(4);
                    }
                }
            }
            resVo.add(vo);
        }
        return resVo;
    }

    @Transactional
    public void edit(OrderEditReqVo reqVo) {
        Order order = orderMapper.selectById(reqVo.getId());

        if (reqVo.getCustomerId() != null) {
            Customer customer = customerMapper.selectById(reqVo.getCustomerId());
            if (customer == null) {
                throw SyExceptionUtils.e("没有找到该客户");
            }
            order.setCustomerId(reqVo.getCustomerId());
            order.setCustomerCode(customer.getMyCode());
            order.setCustomerName(customer.getName());
        }
        if (reqVo.getDeliveryDate() != null) {
            order.setDeliveryDateTime(reqVo.getDeliveryDate());
        }
        if (reqVo.getOrderPriority() != null) {
            order.setOrderPriority(reqVo.getOrderPriority());
        }
        if (reqVo.getOrderWeight() != null) {
            order.setOrderWeight(reqVo.getOrderWeight());
        }
        if (StringUtils.hasText(reqVo.getFrameType())) {
            order.setFrameType(reqVo.getFrameType());
        }
        if (StringUtils.hasText(reqVo.getPlannedMonth())) {
            order.setPlannedMonth(reqVo.getPlannedMonth());
        }
        if (StringUtils.hasText(reqVo.getOrderConstructNo())) {
            order.setConstructNo(reqVo.getOrderConstructNo());
        }
        if (reqVo.getOrderQty() != null) {
            order.setOrderQty(reqVo.getOrderQty());
        }
        orderMapper.updateById(order);

    }

    public BaseListResVo<OrderBomResVo> bom(BaseIdReqVo reqVo) {

        LambdaQueryWrapper<OrderBom> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(OrderBom::getOrderId, reqVo.getId());
        List<OrderBom> orderBomList = orderBomMapper.selectList(wrapper);
        return BaseListResVo.of(orderBomList, OrderBomResVo.class);
    }

    public BaseListResVo<OrderBomListResVo> bomList(BaseIdReqVo reqVo) {

        LambdaQueryWrapper<OrderBom> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(OrderBom::getId, reqVo.getId());
        wrapper.or();
        wrapper.eq(OrderBom::getPid, reqVo.getId());
        List<OrderBom> orderBomList = orderBomMapper.selectList(wrapper);

        if (CollUtil.isEmpty(orderBomList)) {
            return BaseListResVo.empty();
        }

        BaseListResVo<OrderBomListResVo> resVo = BaseListResVo.of(orderBomList, OrderBomListResVo.class);


        List<String> plmIdList = orderBomList.stream().map(OrderBom::getPlmId).distinct().collect(Collectors.toList());
        List<OrderPart> orderPartList = orderPartMapper.lambdaQuery().in(OrderPart::getPlmId, plmIdList).list();

        Map<String, OrderPart> orderPartMap = orderPartList.stream().collect(Collectors.toMap(OrderPart::getPlmId, Function.identity()));
        List<String> workChainList = orderBomList.stream().map(OrderBom::getWorkChain).distinct().collect(Collectors.toList());
        List<ProcessChain> list = processChainMapper.lambdaQuery().in(ProcessChain::getMyCode, workChainList).list();
        Map<String, ProcessChain> collect = list.stream().collect(Collectors.toMap(ProcessChain::getMyCode, Function.identity()));


        Order order = orderMapper.selectById(orderBomList.get(0).getOrderId());
        for (OrderBomListResVo datum : resVo.getData()) {
            datum.setOrderCode(order.getOrderCode());
            datum.setConstructNo(order.getConstructNo());
            datum.setWeight(datum.getMaterWeight());
            OrderPart orderPart = orderPartMap.get(datum.getPlmId());
            if (orderPart != null) {
                datum.setLength(orderPart.getLength());
                datum.setWidth(orderPart.getWidth());
                datum.setMaterHigh(orderPart.getThickness());
                datum.setWeight(orderPart.getNetWeight());
                datum.setMaterWeight(datum.getWeight());
                datum.setReadyType(orderPart.getSource());
            }

            ProcessChain processChain = collect.get(datum.getWorkChain());
            if (processChain != null) {
                datum.setProcessChainId(processChain.getId());
            }
        }

        return resVo;
    }

    @Transactional
    public void editMbd(OrderEditMbdReqVo reqVo) {
        Order max = orderMapper.lambdaQuery()
                .in(Order::getOrderType, 2, 5)
                .eq(Order::getPlannedMonth, reqVo.getPlannedMonth())
                .ne(Order::getId, reqVo.getId())
                .isNotNull(Order::getSeq)
                .orderByDesc(Order::getSeq)
                .last("LIMIT 1")
                .one();

        Order old = orderMapper.selectById(reqVo.getId());


        LambdaUpdateWrapper<Order> wrapper = Wrappers.lambdaUpdate();
        wrapper.set(reqVo.getOrderQty() != null, Order::getOrderQty, reqVo.getOrderQty());
        wrapper.set(StringUtils.hasText(reqVo.getConstructNo()), Order::getConstructNo, reqVo.getConstructNo());
        wrapper.set(StringUtils.hasText(reqVo.getFrameType()), Order::getFrameType, reqVo.getFrameType());
        wrapper.set(StringUtils.hasText(reqVo.getPlannedMonth()), Order::getPlannedMonth, reqVo.getPlannedMonth());
        if (old.getPlannedMonth() == null || !old.getPlannedMonth().equals(reqVo.getPlannedMonth())) {
            wrapper.set(Order::getSeq, max == null ? 1 : max.getSeq() + 1);
        }

        wrapper.in(Order::getOrderType, 2, 5);
        wrapper.eq(Order::getId, reqVo.getId());
        orderMapper.update(null, wrapper);
    }

    public BaseListResVo<OrderBomPhaseResVo> bomPhase(BaseIdReqVo reqVo) {

        OrderBom bom = orderBomMapper.selectById(reqVo.getId());
        if (bom == null) {
            throw SyExceptionUtils.e("BOM不存在");
        }


        LambdaQueryWrapper<OrderPhase> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(OrderPhase::getBomId, reqVo.getId());
        wrapper.orderByAsc(OrderPhase::getPhaseSeq);
        List<OrderPhase> orderPhases = orderPhaseMapper.selectList(wrapper);
        List<OrderBomPhaseResVo> collect = orderPhases.stream()
                .map(e -> {
                    OrderBomPhaseResVo target = MkBeanUtils.copyProperties(e, OrderBomPhaseResVo.class);

                    target.setApsGroupCode(e.getWorkGroupNumber());
                    target.setApsPhaseName(e.getPhaseName());
                    target.setApsPhaseCode(e.getPhaseCode());
                    target.setApsPhaseSeq(e.getPhaseSeq());
                    if (e.getWorkTime() != null) {
                        target.setApsWorkTime(new BigDecimal(e.getWorkTime()).divide(new BigDecimal(60), 2, RoundingMode.HALF_UP).toPlainString());
                    }
                    target.setErpGroupCode(e.getOpCode());
                    target.setErpPhaseCode(e.getOp());
                    if (e.getOriWorkTime() != null) {
                        target.setErpWorkTime(new BigDecimal(e.getOriWorkTime()).divide(new BigDecimal(60), 2, RoundingMode.HALF_UP).toPlainString());
                    }

                    return target;
                })
                .collect(Collectors.toList());
        return new BaseListResVo<>(collect);
    }

    public BasePageResVo<OrderPubListResVo> erpPubList(OrderPubListReqVo reqVo) {
        LambdaQueryWrapper<Order> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StringUtils.hasText(reqVo.getOrderCode()), Order::getOrderCode, reqVo.getOrderCode());
        wrapper.like(StringUtils.hasText(reqVo.getConstructNo()), Order::getConstructNo, reqVo.getConstructNo());
        wrapper.eq(!ObjectUtils.isEmpty(reqVo.getPushStatus()), Order::getPushStatus, reqVo.getPushStatus());
        if (reqVo.getOrderStatus() != null) {
            if (reqVo.getOrderStatus() == 6) {
                wrapper.in(Order::getOrderStatus, 6, 7);
            } else {
                wrapper.eq(Order::getOrderStatus, reqVo.getOrderStatus());
            }
        } else {
            wrapper.ge(Order::getOrderStatus, 6);
        }

        if (reqVo.getType() == null || reqVo.getType().equals(1)) {
            wrapper.in(Order::getOrderType, 1, 3, 4);
        } else {
            wrapper.eq(Order::getOrderType, reqVo.getType());
        }
        wrapper.orderByDesc(Order::getId);
        wrapper.orderByDesc(Order::getSerialCode);
        wrapper.orderByDesc(Order::getMaterCode);
        Page<Order> orderPage = orderMapper.selectPage(reqVo.toPage(), wrapper);

        BasePageResVo<OrderPubListResVo> orderListResVoBasePageResVo = BasePageResVo.of(orderPage, OrderPubListResVo.class);
        for (OrderPubListResVo datum : orderListResVoBasePageResVo.getData()) {
            datum.setConstructNo(datum.getConstructNo());
            datum.setDeliveryDate(datum.getDeliveryDateTime());
            datum.setFactoryCode("170");
        }

        return orderListResVoBasePageResVo;
    }

    public BasePageResVo<OrderSchedulingListResVo> schedulingList(OrderSchedulingListReqVo reqVo) {
        LambdaQueryWrapper<Order> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StringUtils.hasText(reqVo.getMaterCode()), Order::getMaterCode, reqVo.getMaterCode());
        wrapper.like(StringUtils.hasText(reqVo.getOrderCode()), Order::getOrderCode, reqVo.getOrderCode());
        wrapper.like(StringUtils.hasText(reqVo.getConstructNo()), Order::getConstructNo, reqVo.getConstructNo());
        wrapper.in(Order::getOrderStatus, 3, 4, 5);
        wrapper.in(Order::getOrderType, 1, 3, 4);
        wrapper.orderByAsc(Order::getSeq);
        Page<Order> orderPage = orderMapper.selectPage(reqVo.toPage(), wrapper);

        BasePageResVo<OrderSchedulingListResVo> orderListResVoBasePageResVo = BasePageResVo.of(orderPage, OrderSchedulingListResVo.class);
        for (OrderSchedulingListResVo datum : orderListResVoBasePageResVo.getData()) {
            datum.setConstructNo(datum.getConstructNo());
            datum.setDeliveryDate(datum.getDeliveryDateTime());
            datum.setFactoryCode("170");

        }
        return orderListResVoBasePageResVo;
    }

    @Transactional
    public List<ApsOrder> schedule(OrderScheduleReqVo reqVo, ApsBatch apsBatch) {

        // 验证
        // 判断是否有排产中的订单，如果有则提示
        LambdaQueryWrapper<Order> scheduleOrderWrapper = Wrappers.lambdaQuery();
        scheduleOrderWrapper.eq(Order::getOrderStatus, 4);
//        scheduleOrderWrapper.in(Order::getOrderType, 1, 3, 4);
        Integer scheduleOrderCount = orderMapper.selectCount(scheduleOrderWrapper);

        if (scheduleOrderCount > 0) {
            throw SyExceptionUtils.e("有排产中的订单，请稍后再试");
        }
        // 取出所有待排产的订单
        LambdaQueryWrapper<Order> preScheduleOrderWrapper = Wrappers.lambdaQuery();
        preScheduleOrderWrapper.in(Order::getOrderStatus, 3, 5);
//        preScheduleOrderWrapper.in(Order::getOrderType, 1, 3, 4);
        if (apsBatch != null) {
            preScheduleOrderWrapper.eq(Order::getBatchId, apsBatch.getId());
        }
        List<Order> orders = orderMapper.selectList(preScheduleOrderWrapper);
        if (CollUtil.isEmpty(orders)) {
            throw SyExceptionUtils.e("没有待排产的订单");
        }

        List<Integer> orderIds = orders.stream().map(BaseEntity::getId).collect(Collectors.toList());


        // 对apsOrders进行分组排序
        return apsOrderMapper.selectList(Wrappers.<ApsOrder>lambdaQuery()
                        .in(ApsOrder::getOrderId, orderIds)
//                .in(ApsOrder::getOrderType, 1, 3, 4)
        );

    }

    @Transactional
    public List<ApsOrder> scheduleMove(OrderScheduleReqVo reqVo, ApsBatchListResVo apsBatch) {

        // 验证
        // 判断是否有排产中的订单，如果有则提示
        LambdaQueryWrapper<Order> scheduleOrderWrapper = Wrappers.lambdaQuery();
        scheduleOrderWrapper.lt(Order::getOrderStatus, 6);
        Integer scheduleOrderCount = orderMapper.selectCount(scheduleOrderWrapper);

        if (scheduleOrderCount > 0) {
            throw SyExceptionUtils.e("有排产中的订单，请稍后再试");
        }
        // 取出所有待排产的订单

        LambdaQueryWrapper<Order> preScheduleOrderWrapper = Wrappers.lambdaQuery();
        preScheduleOrderWrapper.eq(Order::getOrderStatus, 6);
        if (apsBatch != null) {
            preScheduleOrderWrapper.in(Order::getId, apsBatch.getData().stream().map(ApsBatchListResVo::getId).collect(Collectors.toList()));
        }
        List<Order> orders = orderMapper.selectList(preScheduleOrderWrapper);
        if (CollUtil.isEmpty(orders)) {
            throw SyExceptionUtils.e("没有待排产的订单");
        }
        reqVo.setCacheOrder(orders);

        List<Integer> orderIds = orders.stream().map(BaseEntity::getId).collect(Collectors.toList());


        // 对apsOrders进行分组排序
        return apsOrderMapper.selectList(Wrappers.<ApsOrder>lambdaQuery()
                .in(ApsOrder::getOrderId, orderIds)
        );

    }

    @Transactional
    public List<ApsOrder> publish() {
        List<Integer> orderType = Lists.newArrayList(1, 3, 4);
        List<String> orderTypeSuff = Lists.newArrayList("C", "L", "T", "B");

        // 判断是否有未排产或者排产中的，如果有则提示退出
        Integer noStatus = orderMapper.selectCount(Wrappers.<Order>lambdaQuery()
                .eq(Order::getOrderStatus, 3)
                .in(Order::getOrderType, orderType)
        );
        if (noStatus > 0) {
            throw SyExceptionUtils.e("有未排产的记录");
        }

        Integer processStatus = orderMapper.selectCount(Wrappers.<Order>lambdaQuery()
                .eq(Order::getOrderStatus, 4)
                .in(Order::getOrderType, orderType)
        );
        if (processStatus > 0) {
            throw SyExceptionUtils.e("有正在排产中的数据");
        }

        List<ApsOrder> apsOrders = apsOrderMapper.lambdaQuery()
                .eq(ApsOrder::getOrderStatus, 5)
                .in(ApsOrder::getOrderType, orderType)
                .list();

        if (CollUtil.isEmpty(apsOrders)) {
            throw SyExceptionUtils.e("没有找到已排产的数据");
        }

        List<Integer> collect = apsOrders.stream().map(ApsOrder::getOrderId).collect(Collectors.toList());

        orderMapper.update(null, Wrappers.<Order>lambdaUpdate()
                .set(Order::getOrderStatus, 6)
                .set(Order::getPushStatus, 1)
                .set(Order::getLocked, 2)
                .in(Order::getOrderType, orderType)
                .in(Order::getId, collect)
        );

        List<Integer> apsIds = apsOrders.stream().map(BaseEntity::getId).collect(Collectors.toList());

        apsOrderMapper.update(null, Wrappers.<ApsOrder>lambdaUpdate()
                .set(ApsOrder::getOrderStatus, 6)
                .set(ApsOrder::getLocked, 2)
                .in(ApsOrder::getOrderType, orderType)
                .in(BaseEntity::getId, apsIds)
        );

        // 更新apsWorkOrder
        apsWorkOrderMapper.update(null, Wrappers.<ApsWorkOrder>lambdaUpdate()
                .set(ApsWorkOrder::getStatus, 2)
                .in(ApsWorkOrder::getOrderType, orderType)
                .in(ApsWorkOrder::getApsOrderId, apsIds)
        );
        // 更新apsWorkDetailMapper
        apsWorkDetailMapper.update(null, Wrappers.<ApsWorkDetail>lambdaUpdate()
                .set(ApsWorkDetail::getStatus, 2)
                .in(ApsWorkDetail::getOrderType, orderType)
                .in(ApsWorkDetail::getApsOrderId, apsIds)
        );
        // 更新apsDetailWeekdayMapper
        apsDetailWeekdayMapper.update(null, Wrappers.<ApsDetailWeekday>lambdaUpdate()
                .set(ApsDetailWeekday::getState, 2)
                .in(ApsDetailWeekday::getOrderType, orderType)
                .in(ApsDetailWeekday::getApsOrderId, apsIds)
        );

        LambdaUpdateWrapper<ApsBatch> wrapper = Wrappers.lambdaUpdate();
        wrapper.eq(ApsBatch::getStatus, 1);
        wrapper.orderByDesc(ApsBatch::getSchedulingDateTime);
        wrapper.last(" limit 1");
        ApsBatch apsBatch = apsBatchMapper.selectOne(wrapper);

        apsBatch.setStatus(2);
        apsBatchMapper.updateById(apsBatch);

        apsBatchMapper.deleteNoPub(apsBatch.getId());

        // 外揽订单发布后直接开工!
        if (CollUtil.isNotEmpty(collect)) {
            List<Order> orders = orderMapper.selectBatchIds(collect);
            for (Order order : orders) {
                if (order.getOrderType().equals(3)) {
                    order.setOrderStatus(8);
                    if (order.getSuffix() != null && orderTypeSuff.contains(order.getSuffix())) {
                        order.setPushStatus(0);
                    }
                    orderMapper.updateById(order);
                }
            }

        }

        return apsOrders;
    }

    @Transactional
    public void pubFallback(BaseIdsReqVo reqVo) {

        for (Integer id : reqVo.getIds()) {
            Order order = orderMapper.selectById(id);
            if (order == null) {
                throw SyExceptionUtils.e("没有找到该订单!");
            }

            if (!order.getLocked().equals(1)) {
                throw SyExceptionUtils.e("该订单已锁定，无法回退");
            }

            // 有套料结果存在，无法进行回退
            List<SinoCamReceiveNestPart> nestPartList = sinoCamReceiveNestPartMapper.lambdaQuery().eq(SinoCamReceiveNestPart::getOrderId, id).list();
            if (CollUtil.isNotEmpty(nestPartList)) {
                SinoCamReceiveNestPart nestPart = nestPartList.get(0);
                String str = nestPart.getPlateCode();
                throw SyExceptionUtils.e("该订单存在套料结果，请先撤回套料结果：{}", str);
            }

            Integer batchId = order.getBatchId();

            LambdaUpdateWrapper<Order> wr1 = Wrappers.lambdaUpdate();
            wr1.set(Order::getOrderStatus, 3);
            wr1.set(Order::getPlanStartDateTime, null);
            wr1.set(Order::getPlanEndDateTime, null);
            wr1.set(Order::getBatchId, null);
            wr1.set(Order::getLocked, 1);
            wr1.eq(Order::getId, order.getId());
            orderMapper.update(null, wr1);


            // 检查batchId下是否还有其他的订单，如果没有则删除
            LambdaQueryWrapper<Order> wrapper = Wrappers.lambdaQuery();
            wrapper.eq(Order::getBatchId, batchId);
            wrapper.ne(Order::getId, order.getId());
            Integer i = orderMapper.selectCount(wrapper);
            if (i == 0) {
                apsBatchMapper.deleteData(batchId);
            }


            List<ApsOrder> apsOrders = apsOrderMapper.selectList(Wrappers.<ApsOrder>lambdaQuery()
                    .eq(ApsOrder::getOrderId, reqVo.getIds().get(0))
            );
            for (ApsOrder apsOrder : apsOrders) {
                LambdaUpdateWrapper<ApsOrder> wr = Wrappers.lambdaUpdate();
                wr.set(ApsOrder::getOrderStatus, 3);
                wr.set(ApsOrder::getPlanStartDateTime, null);
                wr.set(ApsOrder::getPlanEndDateTime, null);
                wr.eq(ApsOrder::getId, apsOrder.getId());
                apsOrderMapper.update(null, wr);
            }

            // 通知立体库删除该订单下的外购件领料单
            try {
                List<ApsWorkOrder> apsWorkOrderList = apsWorkOrderMapper.lambdaQuery()
                        .eq(ApsWorkOrder::getOrderId, order.getId())
                        .eq(ApsWorkOrder::getWorkChain, "WL")
                        .isNotNull(ApsWorkOrder::getPickCode)
                        .list();
                if (CollUtil.isNotEmpty(apsWorkOrderList)) {
                    List<MesPicking> pickList = new ArrayList<>();
                    MesPicking picking = new MesPicking();
                    ApsWorkOrder apsWorkOrder = apsWorkOrderList.get(0);
                    picking.setPickListNo(Long.valueOf(apsWorkOrder.getPickCode()));
                    pickList.add(picking);
                    Result result = wmsLtkApiClient.deletePickIng(pickList);
                    log.info("立体库删除外购件领料单结果：", result);
                }
            } catch (Exception e) {
                log.error("立体库删除外购件领料单异常：", e);
            }

            apsWorkOrderMapper.deleteOrderId(order.getId());
            apsWorkDetailMapper.deleteOrderId(order.getId());
            apsDetailWeekdayMapper.deleteOrderId(order.getId());

            sinoCamPushPlanMapper.deletePreOrder(order.getId());
            sinoCamPushDrawingMapper.deletePreOrder(order.getId());

            hexagonPackagePushMapper.deletePreOrder(order.getId());
        }


    }

    public BaseSelectResVo doingList() {

        List<Order> orderList = orderMapper.lambdaQuery()
                .ge(Order::getOrderStatus, 6)
                .lt(Order::getOrderStatus, 9)
                .in(Order::getOrderType, 1, 3, 4)
                .list();

        List<BaseSelectItemResVo> collect = orderList.stream()
                .map(e -> {
                    BaseSelectItemResVo r = new BaseSelectItemResVo();
                    r.setText(e.getOrderCode() + "-" + e.getMaterName());
                    r.setValue(e.getId());
                    return r;
                })
                .collect(Collectors.toList());

        return BaseSelectResVo.of(collect);
    }

    @Transactional
    public void lock(BaseIdsReqVo reqVo) {
        LambdaUpdateWrapper<Order> wrapper = Wrappers.lambdaUpdate();
        wrapper.set(Order::getLocked, 2);
        wrapper.in(Order::getId, reqVo.getIds());
        wrapper.ge(Order::getOrderStatus, 6);
        orderMapper.update(null, wrapper);

        // 子订单也锁定
//        LambdaUpdateWrapper<ApsOrder> wrapper1 = Wrappers.lambdaUpdate();
//        wrapper1.set(ApsOrder::getLocked, 2);
//        wrapper1.in(ApsOrder::getOrderId, reqVo.getIds());
//        wrapper1.ge(ApsOrder::getOrderStatus, 6);
//        apsOrderMapper.update(null, wrapper1);

    }

    @Transactional
    public void unlock(BaseIdsReqVo reqVo) {
        LambdaUpdateWrapper<Order> wrapper = Wrappers.lambdaUpdate();
        wrapper.set(Order::getLocked, 1);
        wrapper.in(Order::getId, reqVo.getIds());
        wrapper.ge(Order::getOrderStatus, 6);
        orderMapper.update(null, wrapper);

//        LambdaUpdateWrapper<ApsOrder> wrapper1 = Wrappers.lambdaUpdate();
//        wrapper1.set(ApsOrder::getLocked, 1);
//        wrapper1.in(ApsOrder::getOrderId, reqVo.getIds());
//        wrapper1.ge(ApsOrder::getOrderStatus, 6);
//        apsOrderMapper.update(null, wrapper1);
    }

    public OrderGroupLoadsResVo groupLoads(OrderGroupLoadsReqVo reqVo) {

        if (reqVo.getStartDate() == null || reqVo.getEndDate() == null) {
            throw SyExceptionUtils.e("请传入开始时间和结束时间");
        }

        long until = reqVo.getStartDate().until(reqVo.getEndDate(), ChronoUnit.DAYS);

        List<Phase> list = phaseMapper.lambdaQuery().eq(Phase::getWorkloadShow, 2).list();
        List<String> phaseHidden = list.stream().map(Phase::getMyCode).distinct().collect(Collectors.toList());

        QueryWrapper<ApsDetailWeekday> query = Wrappers.query();
        query.ge(reqVo.getOrderId() != null, "awd.order_id", reqVo.getOrderId());
//        query.ge("adw.state", 2);
        query.eq("awd.deleted", 0);
        query.in("awd.order_type", 1, 3, 4);
        query.notIn("awd.phase_code", phaseHidden);
        query.in(CollUtil.isNotEmpty(reqVo.getGroupIds()), "awd.group_id", reqVo.getGroupIds());
        query.ge(reqVo.getStartDate() != null, "awd.plan_start_date_time", reqVo.getStartDate().toString() + " 06:00:00");
        query.le(reqVo.getEndDate() != null, "awd.plan_start_date_time", reqVo.getEndDate().plusDays(1).toString() + " 06:00:00");
        query.ge(" awd.status ", 2);
        query.groupBy("shift_day, group_id");
        //   query.having("work_date >= ? and work_date <= ?", reqVo.getStartDate(), reqVo.getEndDate());

        List<OrderGroupLoadsDataResVo> data = orderMapper.groupLoads(query);
        if (CollUtil.isEmpty(data)) {
            return new OrderGroupLoadsResVo();
        }
        QueryWrapper<ApsDetailWeekday> queryFinsh = Wrappers.query();
        queryFinsh.ge(reqVo.getOrderId() != null, "awd.order_id", reqVo.getOrderId());
        queryFinsh.eq("awd.deleted", 0);
        queryFinsh.in("awd.order_type", 1, 3, 4);
        queryFinsh.notIn("awd.phase_code", phaseHidden);
        queryFinsh.in(CollUtil.isNotEmpty(reqVo.getGroupIds()), "awd.group_id", reqVo.getGroupIds());
        queryFinsh.ge(reqVo.getStartDate() != null, "mwd.actual_end_date_time", reqVo.getStartDate().toString() + " 06:00:00");
        queryFinsh.le(reqVo.getEndDate() != null, "mwd.actual_end_date_time", reqVo.getEndDate().plusDays(1).toString() + " 06:00:00");
        queryFinsh.ge(" awd.status ", 2);
        queryFinsh.groupBy("shift_day, group_id");

        List<OrderGroupLoadsDataResVo> dataFish = orderMapper.groupFishLoads(queryFinsh);
        Map<String, OrderGroupLoadsDataResVo> finishMap = dataFish.stream().collect(Collectors.toMap(item -> item.getGroupId() + "_" + item.getShiftDay(), Function.identity()));


        List<Integer> groupIds = data.stream().map(OrderGroupLoadsDataResVo::getGroupId).distinct().collect(Collectors.toList());
        if (CollUtil.isEmpty(groupIds)) {
            return new OrderGroupLoadsResVo();
        }

        List<StationCount> groups = groupMapper.findStationAbility(Wrappers.<Group>query()
                .eq("s.deleted", 0)
                .in("s.group_id", groupIds)
                .groupBy(" s.group_id, g.my_code, g.name, g.seq")
        );
        Map<Integer, StationCount> groupMap = groups.stream().collect(Collectors.toMap(StationCount::getGroupId, Function.identity()));

        for (OrderGroupLoadsDataResVo datum : data) {
            StationCount g = groupMap.get(datum.getGroupId());

            datum.setTotalWorkTime(ApsConstant.WORK_TIME * g.getStationCount());
            datum.setGroupName(g.getName());
            datum.setGroupCode(g.getMyCode());
            datum.setFinishWorkTime(finishMap.get(datum.getGroupId() + "_" + datum.getShiftDay()) != null ? finishMap.get(datum.getGroupId() + "_" + datum.getShiftDay()).getFinishWorkTime() : 0);
            datum.setFinishWorkLoad(new BigDecimal(datum.getFinishWorkTime()).divide(new BigDecimal(datum.getTotalWorkTime()), 4, RoundingMode.HALF_UP));
            datum.setWorkLoad(new BigDecimal(datum.getUsedWorkTime()).divide(new BigDecimal(datum.getTotalWorkTime()), 4, RoundingMode.HALF_UP));
        }

        OrderGroupLoadsResVo resVo = new OrderGroupLoadsResVo();
        resVo.setData(data);

        //  顶部统计报表统计
        Map<Integer, OrderGroupLoadsDataResVo> collect = data.stream().collect(Collectors.toMap(OrderGroupLoadsDataResVo::getGroupId, e -> e, (e1, e2) -> {
            OrderGroupLoadsDataResVo rr = new OrderGroupLoadsDataResVo();
            rr.setGroupId(e1.getGroupId());
            rr.setGroupName(e1.getGroupName());
            rr.setGroupCode(e1.getGroupCode());
//            rr.setWorkLoad(e1.getWorkLoad().add(e2.getWorkLoad()).divide(new BigDecimal(until + 1), 2, RoundingMode.HALF_UP));
            rr.setUsedWorkTime(e1.getUsedWorkTime() + e2.getUsedWorkTime());

            return rr;
        }));


        for (OrderGroupLoadsDataResVo value : collect.values()) {
            StationCount g = groupMap.get(value.getGroupId());
            value.setTotalWorkTime(ApsConstant.WORK_TIME * g.getStationCount() * ((int) until + 1));
//            value.setFinishWorkLoad(new BigDecimal(value.getFinishWorkTime()).divide(new BigDecimal(value.getTotalWorkTime()), 4, RoundingMode.HALF_UP));
            value.setWorkLoad(new BigDecimal(value.getUsedWorkTime()).divide(new BigDecimal(value.getTotalWorkTime()), 4, RoundingMode.HALF_UP));
        }

        resVo.setTopTen(collect.values().stream().sorted(Comparator.comparing(OrderGroupLoadsDataResVo::getWorkLoad).reversed()).limit(10).collect(Collectors.toList()));

        return resVo;

    }

    public BaseListResVo<OrderProdGanttResVo> prodGantt(OrderProdGanttReqVo reqVo) {

        QueryWrapper<ApsDetailWeekday> wrapper = Wrappers.query();
        wrapper.ge("state", 2);
        wrapper.eq("deleted", 0);
        wrapper.in("order_type", 1, 4);
        wrapper.eq(reqVo.getOrderId() != null, "order_id", reqVo.getOrderId());
        wrapper.ge(reqVo.getStartDate() != null, "shift_day", reqVo.getStartDate());
        wrapper.le(reqVo.getEndDate() != null, "shift_day", reqVo.getEndDate());
        wrapper.groupBy("shift_day, group_id, order_id");
        wrapper.orderByAsc("shift_day, order_id, group_id");

        List<OrderProdGanttArrayResVo> list = apsDetailWeekdayMapper.selectProdGantt(wrapper);
        if (CollUtil.isEmpty(list)) {
            return BaseListResVo.empty();
        }

        List<Integer> groupIds = list.stream().map(OrderProdGanttArrayResVo::getGroupId).distinct().collect(Collectors.toList());
        List<StationCount> groups = groupMapper.findStationCount(Wrappers.<Group>query()
                .eq("s.deleted", 0)
                .in("s.group_id", groupIds)
                .groupBy("s.group_id")
        );

//        List<OrderProdGanttArrayResVo> orderProdGanttArrayResVos = groupMapper.countStation(Wrappers.<Group>query()
//                .eq("g.deleted", 0)
//                .eq("g.type", 2)
//                .eq("sg.default_group", 1)
//                .groupBy("g.id")
//        );

        Map<Integer, StationCount> collect = groups.stream().collect(Collectors.toMap(StationCount::getGroupId, Function.identity()));

        for (OrderProdGanttArrayResVo r : list) {
            StationCount orderProdGanttArrayResVo1 = collect.get(r.getGroupId());
            if (orderProdGanttArrayResVo1 != null) {
                r.setWorkTime(r.getWorkTime() / orderProdGanttArrayResVo1.getStationCount());
            }
        }

        Map<Integer, Map<LocalDate, Map<Integer, OrderProdGanttArrayResVo>>> map = list.stream().collect(
                Collectors.groupingBy(OrderProdGanttArrayResVo::getGroupId,
                        Collectors.groupingBy(OrderProdGanttArrayResVo::getShiftDay,
                                Collectors.toMap(OrderProdGanttArrayResVo::getOrderId, Function.identity()))));

        List<String> colors = Lists.newArrayList("#93E5A0", "#F1A599", "#3D93F6", "#F6AF43", "#6BC471", "#47CBE6", "#9FD2FF", "#B29FFF", "#FFDA61", "#FF7F50", "#FFD299", "#8FBF9F");

        List<Order> orders = orderMapper.selectBatchIds(list.stream().map(OrderProdGanttArrayResVo::getOrderId).distinct().collect(Collectors.toList()));
        Map<String, String> subOrderIdMap = new HashMap<>();

        Map<Integer, Order> orderMap = orders.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));
        for (Map.Entry<Integer, Map<LocalDate, Map<Integer, OrderProdGanttArrayResVo>>> groupIdEntry : map.entrySet()) {
            for (Map.Entry<LocalDate, Map<Integer, OrderProdGanttArrayResVo>> shiftDayEntry : groupIdEntry.getValue().entrySet()) {
                LocalDate key = shiftDayEntry.getKey();
                LocalDateTime startDate = LocalDateTime.of(key, LocalTime.of(0, 0, 0));
                for (Map.Entry<Integer, OrderProdGanttArrayResVo> orderIdEntry : shiftDayEntry.getValue().entrySet()) {
                    OrderProdGanttArrayResVo orderProdGanttArrayResVo = orderIdEntry.getValue();
                    orderProdGanttArrayResVo.setStart(startDate);
                    orderProdGanttArrayResVo.setEnd(startDate.plusSeconds(orderProdGanttArrayResVo.getWorkTime()));
                    startDate = orderProdGanttArrayResVo.getEnd();


                    if (orderMap.get(orderProdGanttArrayResVo.getOrderId()) == null) {
                        continue;
                    }
                    orderProdGanttArrayResVo.setOrderQty(orderMap.get(orderProdGanttArrayResVo.getOrderId()).getOrderQty());
                    orderProdGanttArrayResVo.setFinishQty(orderMap.get(orderProdGanttArrayResVo.getOrderId()).getFinishQty());
                    orderProdGanttArrayResVo.setConstructNo(orderMap.get(orderProdGanttArrayResVo.getOrderId()).getConstructNo());
                    orderProdGanttArrayResVo.setOrderCode(orderMap.get(orderProdGanttArrayResVo.getOrderId()).getOrderCode());
                    orderProdGanttArrayResVo.setMaterCode(orderMap.get(orderProdGanttArrayResVo.getOrderId()).getMaterCode());
                    orderProdGanttArrayResVo.setMaterName(orderMap.get(orderProdGanttArrayResVo.getOrderId()).getMaterName());
                    orderProdGanttArrayResVo.setWorkTimeMinutes(new BigDecimal(orderProdGanttArrayResVo.getWorkTime()).divide(new BigDecimal(60), 2, RoundingMode.HALF_UP));
                    orderProdGanttArrayResVo.setPlanStartDateTime(orderMap.get(orderProdGanttArrayResVo.getOrderId()).getPlanStartDateTime());
                    orderProdGanttArrayResVo.setPlanEndDateTime(orderMap.get(orderProdGanttArrayResVo.getOrderId()).getPlanEndDateTime());

                    String s = subOrderIdMap.computeIfAbsent(orderProdGanttArrayResVo.getConstructNo(), k -> colors.get(subOrderIdMap.size() % colors.size()));
                    orderProdGanttArrayResVo.setColor(s);

                }
            }
        }

        Map<Integer, List<OrderProdGanttArrayResVo>> collect1 = list.stream().collect(Collectors.groupingBy(OrderProdGanttArrayResVo::getGroupId));

        List<OrderProdGanttResVo> collect2 = collect1.keySet()
                .stream()
                .map(e -> {
                    OrderProdGanttResVo r = new OrderProdGanttResVo();
                    r.setGroupId(e);
                    r.setGroupCode(collect.get(e).getMyCode());
                    r.setGroupName(collect.get(e).getName());
                    r.setGroupSeq(collect.get(e).getSeq());
                    r.setGtArray(collect1.get(e));
                    return r;
                })
                .sorted(Comparator.comparing(OrderProdGanttResVo::getGroupSeq))
                .collect(Collectors.toList());

        return new BaseListResVo<>(collect2);
    }

    public BaseListResVo<OrderGroupLoadsDetailResVo> groupLoadsDetail(OrderGroupLoadsDetailReqVo reqVo) {

        if (reqVo.getWorkDay() == null) {
            throw SyExceptionUtils.e("请传入开始时间和结束时间");
        }

        Group group = groupMapper.selectOne(Wrappers.<Group>lambdaQuery().eq(Group::getMyCode, reqVo.getGroupCode()));

        List<Phase> list = phaseMapper.lambdaQuery().eq(Phase::getWorkloadShow, 2).list();
        List<String> phaseHidden = list.stream().map(Phase::getMyCode).distinct().collect(Collectors.toList());

        QueryWrapper<ApsDetailWeekday> query = Wrappers.query();
        //  where adw.deleted = 0 and adw.`state` >= 2 and adw.group_id ? in and shift_day = ?\n" +
        //            "order by adw.plan_start_date_time
        query.eq("adw.deleted", 0);
//        query.ge("adw.state", 2);
        query.in("wd.order_type", 1, 3, 4);
        query.eq("adw.group_id", group.getId());
        query.eq("adw.shift_day", reqVo.getWorkDay());
        query.notIn("adw.phase_code", phaseHidden);
        query.in(" wd.`status` ", 2, 3);
        query.orderByAsc("adw.plan_start_date_time");
        List<OrderGroupLoadsDetailResVo> apsDetailWeekdays = apsDetailWeekdayMapper.selectAll(query);

        for (OrderGroupLoadsDetailResVo apsDetailWeekday : apsDetailWeekdays) {
            apsDetailWeekday.setSeqStr(PkgUtils.gen(apsDetailWeekday.getSeq()));
        }


        return new BaseListResVo<>(apsDetailWeekdays);
    }

    @Transactional
    public void unMoveAps(BaseIdReqVo reqVo) {
        Order order = orderMapper.selectById(reqVo.getId());

        // 1.清理aps排产的信息
        apsOrderMapper.deleteOrderId(reqVo.getId());
        apsWorkOrderMapper.deleteOrderId(reqVo.getId());
        apsWorkDetailMapper.deleteOrderId(reqVo.getId());
        apsDetailWeekdayMapper.deleteOrderId(reqVo.getId());

        // 2.重置倒排的状态
        reverseOrderMapper.update(null, Wrappers.<ReverseOrder>lambdaUpdate()
                .set(ReverseOrder::getMoveFlag, 1)
                .eq(ReverseOrder::getOrderId, reqVo.getId())
                .eq(ReverseOrder::getMoveFlag, 2)
        );

        // 3.重置订单状态
        LambdaUpdateWrapper<Order> wrapper = Wrappers.lambdaUpdate();
        wrapper.set(Order::getOrderStatus, 2);
        wrapper.set(Order::getBatchId, null);
        wrapper.set(Order::getPlanStartDateTime, null);
        wrapper.set(Order::getPlanEndDateTime, null);
        wrapper.eq(Order::getId, reqVo.getId());
        orderMapper.update(null, wrapper);
        Integer count = orderMapper.lambdaQuery()
                .in(Order::getBatchId, order.getBatchId())
                .count();

        if (count <= 0) {
            apsBatchMapper.deleteData(order.getBatchId());
        }

    }

    @Transactional
    public void moveSeq(BaseIdsReqVo reqVo) {
        List<Order> orders = orderMapper.selectBatchIds(reqVo.getIds());
        Map<Integer, Order> orderIdMap = orders.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));
        int seq = 1;
        List<Integer> statusCodes = Lists.newArrayList(3, 4, 5);//所有待排产的状态

        for (Integer orderId : reqVo.getIds()) {
            Order order = orderIdMap.get(orderId);
            if (!statusCodes.contains(order.getOrderStatus())) {
                throw SyExceptionUtils.e("订单状态不一致[{}] - [{}]", order.getOrderCode(), order.getMaterName());
            }
            order.setSeq(seq++);
            orderMapper.updateById(order);
        }


    }

    public BaseListResVo<OrderGroupLoadsListResVo> groupLoadsList(OrderGroupLoadsListReqVo reqVo) {
        List<Phase> list = phaseMapper.lambdaQuery().eq(Phase::getWorkloadShow, 2).list();
        List<String> phaseHidden = list.stream().map(Phase::getMyCode).distinct().collect(Collectors.toList());

        QueryWrapper<ApsDetailWeekday> query = Wrappers.query();
        query.ge(reqVo.getOrderId() != null, "order_id", reqVo.getOrderId());
        query.ge("state", 2);
        query.eq("deleted", 0);
        query.notIn("phase_code", phaseHidden);
        query.in(CollUtil.isNotEmpty(reqVo.getGroupIds()), "group_id", reqVo.getGroupIds());
        query.ge(reqVo.getStartDate() != null, "shift_day", reqVo.getStartDate());
        query.le(reqVo.getEndDate() != null, "shift_day", reqVo.getEndDate());
        query.groupBy("group_id");

        long until = reqVo.getStartDate().until(reqVo.getEndDate(), ChronoUnit.DAYS);

        List<OrderGroupLoadsListResVo> data = orderMapper.groupLoadsList(query);
        if (CollUtil.isEmpty(data)) {
            return BaseListResVo.empty();
        }


        List<Integer> groupIds = data.stream().map(OrderGroupLoadsListResVo::getGroupId).distinct().collect(Collectors.toList());
        if (CollUtil.isEmpty(groupIds)) {
            return BaseListResVo.empty();
        }

        List<StationCount> groups = groupMapper.findStationCount(Wrappers.<Group>query()
                .eq("s.deleted", 0)
                .in("s.group_id", groupIds)
                .groupBy("s.group_id")
        );
        Map<Integer, StationCount> groupMap = groups.stream().collect(Collectors.toMap(StationCount::getGroupId, Function.identity()));

        for (OrderGroupLoadsListResVo datum : data) {
            StationCount g = groupMap.get(datum.getGroupId());
            datum.setTotalWorkTime(ApsConstant.WORK_TIME * g.getStationCount() * ((int) until + 1));
            datum.setGroupName(g.getName());
            datum.setGroupCode(g.getMyCode());
            datum.setWorkLoad(new BigDecimal(datum.getUsedWorkTime())
                    .divide(new BigDecimal(datum.getTotalWorkTime()), 4, RoundingMode.HALF_UP)
            );
        }

        data.sort(Comparator.comparing(OrderGroupLoadsListResVo::getWorkLoad).reversed());

        return new BaseListResVo<>(data);
    }

    @Transactional
    public List<ApsBatch> afterSchedule(OrderAfterScheduleReqVo reqVo) {

        ApsBatch targetBatch = apsBatchMapper.selectById(reqVo.getBatchId());
        LambdaQueryWrapper<ApsBatch> wrapper = Wrappers.lambdaQuery();
        wrapper.gt(ApsBatch::getCreateDateTime, targetBatch.getCreateDateTime());
        wrapper.eq(ApsBatch::getStatus, 2);
        wrapper.orderByAsc(ApsBatch::getSchedulingDateTime);

        return apsBatchMapper.selectList(wrapper);
    }

    public List<ApsBatch> moveSchedule(OrderMoveScheduleReqVo reqVo) {
        ApsBatch targetBatch = apsBatchMapper.selectById(reqVo.getTargetBatchId());
        LambdaQueryWrapper<ApsBatch> wrapper = Wrappers.lambdaQuery();
        wrapper.gt(ApsBatch::getCreateDateTime, targetBatch.getCreateDateTime());
        wrapper.eq(ApsBatch::getStatus, 2);
        wrapper.notIn(ApsBatch::getId, reqVo.getSourceBatchId());
        wrapper.orderByAsc(ApsBatch::getSchedulingDateTime);

        return apsBatchMapper.selectList(wrapper);
    }

    public void publish(ApsBatch apsBatch) {

        List<ApsOrder> apsOrders = apsOrderMapper.selectList(Wrappers.<ApsOrder>lambdaQuery()
                .eq(ApsOrder::getOrderStatus, 5)
        );

        if (CollUtil.isEmpty(apsOrders)) {
            throw SyExceptionUtils.e("没有找到已排产的数据");
        }

        List<Integer> collect = apsOrders.stream().map(ApsOrder::getOrderId).collect(Collectors.toList());

        orderMapper.update(null, Wrappers.<Order>lambdaUpdate()
                .set(Order::getOrderStatus, 6)
                .set(Order::getPushStatus, 1)
                .set(Order::getLocked, 2)
                .set(Order::getPublishUserCode, SySecurityUtils.getUserCode())
                .set(Order::getPublishDateTime, LocalDateTime.now())
                .in(Order::getId, collect)
        );

        List<Integer> apsIds = apsOrders.stream().map(BaseEntity::getId).collect(Collectors.toList());

        apsOrderMapper.update(null, Wrappers.<ApsOrder>lambdaUpdate()
                .set(ApsOrder::getOrderStatus, 6)
                .set(ApsOrder::getLocked, 2)
                .in(BaseEntity::getId, apsIds)
        );

        // 更新apsWorkOrder
        apsWorkOrderMapper.update(null, Wrappers.<ApsWorkOrder>lambdaUpdate()
                .set(ApsWorkOrder::getStatus, 2)
                .in(ApsWorkOrder::getApsOrderId, apsIds)
        );
        // 更新apsWorkDetailMapper
        apsWorkDetailMapper.update(null, Wrappers.<ApsWorkDetail>lambdaUpdate()
                .set(ApsWorkDetail::getStatus, 2)
                .in(ApsWorkDetail::getApsOrderId, apsIds)
        );
        // 更新apsDetailWeekdayMapper
        apsDetailWeekdayMapper.update(null, Wrappers.<ApsDetailWeekday>lambdaUpdate()
                .set(ApsDetailWeekday::getState, 2)
                .in(ApsDetailWeekday::getApsOrderId, apsIds)
        );


        apsBatch.setStatus(2);
        apsBatchMapper.updateById(apsBatch);

        apsBatchMapper.deleteNoPub(apsBatch.getId());

    }

    public List<ApsOrder> selectChildren(OrderScheduleReqVo reqVo) {
        return ChainWrappers.lambdaQueryChain(apsOrderMapper)
                .eq(ApsOrder::getOrderId, reqVo.getId())
                .orderByAsc(ApsOrder::getSeq)
                .list();
    }

    public BaseListResVo<OrderWorkLoadsResVo> workLoads(OrderWorkLoadsReqVo reqVo) {

        // 获取计划时间
        Map<LocalDate, Map<Integer, Integer>> stationData = getPlanMap(reqVo);

        long until = reqVo.getStartDate().until(reqVo.getEndDate(), ChronoUnit.DAYS) + 1;
        List<Station> staList = stationMapper.lambdaQuery().in(Station::getId, reqVo.getStationIds()).list();
        Map<Integer, List<Station>> staGroupMap = staList.stream().collect(Collectors.groupingBy(Station::getGroupId));
        List<Group> groupList = groupMapper.lambdaQuery().in(Group::getId, staList.stream().map(Station::getGroupId).distinct().collect(Collectors.toList())).orderByAsc(Group::getMyCode).list();

        List<Integer> collect = staList.stream().map(Station::getId).distinct().collect(Collectors.toList());
        List<Station> stationList = stationMapper.lambdaQuery().in(Station::getId, collect).list();
        Map<Integer, Station> stationMap = stationList.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));


        List<OrderWorkLoadsResVo> resVo = new ArrayList<>();
        for (Group group : groupList) {

            OrderWorkLoadsResVo r = new OrderWorkLoadsResVo();
            r.setId(group.getId());
            r.setTitle(group.getName());
            r.setMyCode(group.getMyCode());
            r.setData(new ArrayList<>());
            resVo.add(r);

            List<Station> stations = staGroupMap.get(group.getId());
            if (CollUtil.isEmpty(stations)) {
                continue;
            }
            for (int i = 0; i < until; i++) {
                LocalDate currentDay = reqVo.getStartDate().plusDays(i);

                OrderWorkLoadsDataResVo rr = new OrderWorkLoadsDataResVo();
                rr.setPlanMinutes(0);
                rr.setDay(currentDay);
                rr.setStationCount(stations.size());

                rr.setNotReport(0);
                rr.setReport(0);
                rr.setDelayReport(0);

                int workGroupSecond = 0;
                int planMinutes = 0;
                int notReport = 0;
                int report = 0;
                int delayReport = 0;

                // 算出全部时间
                // 算出计划时间
                for (Station station : stations) {

                    System.out.println(station.getId());
                    List<ApsWeekDay> allWeekday = getStationSecond(station.getId(), currentDay);
                    Long reduce1 = allWeekday.stream().filter(w -> w.getWorkState() == 1).map(w -> w.getStartDateTime().until(w.getEndDateTime(), ChronoUnit.SECONDS)).reduce(0L, Long::sum);

                    BigDecimal workAbility = station.getWorkAbility();

                    BigDecimal d = new BigDecimal(reduce1).multiply(workAbility);
                    workGroupSecond = workGroupSecond + d.intValue();

                    // 计划时间
                    Map<Integer, Integer> integerOrderWorkLoadsDataResVoMap = stationData.get(currentDay);

                    if (integerOrderWorkLoadsDataResVoMap == null) {
                        continue;
                    }


                    Integer stationMinut = integerOrderWorkLoadsDataResVoMap.computeIfAbsent(station.getId(), e -> 0);
                    planMinutes = planMinutes + stationMinut;


                    ApsWeekDay startDateTime = allWeekday.stream().min(Comparator.comparing(ApsWeekDay::getStartDateTime)).get();
                    ApsWeekDay endDateTime = allWeekday.stream().min(Comparator.comparing(ApsWeekDay::getEndDateTime)).get();

                    List<ApsWorkDetail> list = apsWorkDetailMapper.lambdaQuery()
                            .ge(ApsWorkDetail::getPlanStartDateTime, startDateTime.getStartDateTime().format(DatePattern.NORM_DATETIME_FORMATTER))
                            .le(ApsWorkDetail::getPlanStartDateTime, endDateTime.getEndDateTime().format(DatePattern.NORM_DATETIME_FORMATTER))
                            .list();

                    for (ApsWorkDetail apsWorkDetail : list) {
                        BigDecimal subtract = apsWorkDetail.getTotalCount().subtract(apsWorkDetail.getFinishCount());
                        if (subtract.compareTo(BigDecimal.ZERO) == 0) {
                            // 如果全部完成，但是延迟完成
                            if (apsWorkDetail.getPlanStartDateTime().isAfter(apsWorkDetail.getActualEndDateTime())) {
                                delayReport = delayReport + (subtract.multiply(new BigDecimal(apsWorkDetail.getWorkTime()))).intValue();
                            } else {
                                report = report + (subtract.multiply(new BigDecimal(apsWorkDetail.getWorkTime()))).intValue();
                            }
                        }

                        if (subtract.compareTo(BigDecimal.ZERO) > 0) {
                            // 如果完成
                            notReport = notReport + (subtract.multiply(new BigDecimal(apsWorkDetail.getWorkTime()))).intValue();
                            report = report + (apsWorkDetail.getTotalWorkTime() - notReport);
                        }


//                        notReport = notReport + subtract.multiply(new BigDecimal(apsWorkDetail.getWorkTime())).intValue();
//
//                        if (apsWorkDetail.getFinishCount().compareTo(BigDecimal.ZERO) <= 0) {
//                            continue;
//                        }
//
//                        if(apsWorkDetail.getActualEndDateTime().isAfter(apsWorkDetail.getPlanEndDateTime())){
//                            delayReport = delayReport + apsWorkDetail.getFinishCount().intValue();
//                        } else {
//                            report = report + apsWorkDetail.getFinishCount().intValue();
//                        }


                    }


                }


                rr.setCapacity(workGroupSecond / 60);
                rr.setPlanMinutes(planMinutes / 60);

                rr.setNotReport(rr.getNotReport() / 60);
                rr.setReport(rr.getReport() / 60);
                rr.setDelayReport(rr.getDelayReport() / 60);

                r.getData().add(rr);
            }


        }

        return new BaseListResVo<>(resVo);
    }

    public List<ApsWeekDay> getStationSecond(Integer stationId, LocalDate currentDay) {
        StationWeekdayScheme scheme = stationWeekdaySchemeMapper.lambdaQuery().eq(StationWeekdayScheme::getStationId, stationId).one();
        if (scheme == null) {
            throw SyExceptionUtils.e("没有找到该工位的日历");
        }
        List<Shift> shifts = shiftMapper.selectList(Wrappers.<Shift>lambdaQuery().eq(Shift::getShiftTypeId, scheme.getShiftTypeId()));
        WeekdaySchemeTimeRangeResVo w1 = new WeekdaySchemeTimeRangeResVo();
        w1.setShiftDay(currentDay);

        List<StationWeekdayRule> ruleList = stationWeekdayRuleMapper.selectList(Wrappers.<StationWeekdayRule>lambdaQuery().eq(StationWeekdayRule::getStationWeekdaySchemeId, scheme.getId()));

        List<BreakPeriod> bp = breakPeriodMapper.selectList(Wrappers.<BreakPeriod>lambdaQuery().in(BreakPeriod::getShiftId, shifts.stream().map(BaseEntity::getId).collect(Collectors.toList())));
        List<ApsWeekDay> allWeekday = shifts.stream()
                .map(shift -> {
                    ApsWeekDay newDay = new ApsWeekDay();
                    MkBeanUtils.copyPropertiesIgnore(shift, newDay);
                    newDay.setSchemeId(scheme.getId());
                    newDay.setShiftDay(currentDay);
                    newDay.setShiftSeq(shift.getSeq());
                    newDay.setShiftId(shift.getId());
                    newDay.setStartDateTime(LocalDateTime.of(currentDay.plusDays(shift.getOffsetStartDay()), shift.getStartTime()));
                    newDay.setEndDateTime(LocalDateTime.of(currentDay.plusDays(shift.getOffsetEndDay()), shift.getEndTime()));
                    return newDay;
                })
                .flatMap(newDay -> {

                    List<ApsWeekDay> all = new ArrayList<>();
                    for (BreakPeriod breakPeriod : bp) {
                        if (LocalDateTime.of(currentDay.plusDays(breakPeriod.getOffsetStartDay()), breakPeriod.getStartTime()).isAfter(newDay.getEndDateTime())) {
                            continue;
                        }
                        if (LocalDateTime.of(currentDay.plusDays(breakPeriod.getOffsetEndDay()), breakPeriod.getEndTime()).isBefore(newDay.getStartDateTime())) {
                            continue;
                        }

                        ApsWeekDay apsWeekDay = MkBeanUtils.copyProperties(newDay, ApsWeekDay.class);
                        apsWeekDay.setEndDateTime(LocalDateTime.of(currentDay.plusDays(breakPeriod.getOffsetStartDay()), breakPeriod.getStartTime()));
                        all.add(apsWeekDay);
                        newDay.setStartDateTime(LocalDateTime.of(currentDay.plusDays(breakPeriod.getOffsetEndDay()), breakPeriod.getEndTime()));
                    }
                    all.add(newDay);
                    return all.stream();
                }).collect(Collectors.toList());

//        for (Shift shift : shifts) {
//            WeekdaySchemeTimeRangeItemResVo item  = new WeekdaySchemeTimeRangeItemResVo();
//            item.setShiftSeq(shift.getSeq());
//            item.setOffsetStartDay(shift.getOffsetStartDay());
//            item.setOffsetEndDay(shift.getOffsetEndDay());
//            item.setStartTime(shift.getStartTime());
//            item.setEndTime(shift.getEndTime());
//            item.setShiftId(shift.getId());
//            w.getItem().add(item);
//        }


        // 匹配规则，可以抽成策略模式，数据量大，为了效率不建议
        for (ApsWeekDay w : allWeekday) {
            for (StationWeekdayRule weekdayRule : ruleList) {
                if (weekdayRule.getType() == 4) {
                    if (weekdayRule.getValue().equals(String.valueOf(w.getShiftDay().getDayOfWeek().getValue()))) {
                        w.setDateType(weekdayRule.getDateType());
                        w.setWorkState(weekdayRule.getStatus());
                        w.setWeekdayRuleId(weekdayRule.getId());
                    }
                } else if (weekdayRule.getType() == 1) {
                    String value = weekdayRule.getValue();
                    String[] split = value.split(ProjectConstants.WEEKDAY_RULE_WEEKVALUE_SPLIT);
                    LocalDate start = LocalDate.parse(split[0], DatePattern.NORM_DATE_FORMATTER);
                    LocalDate end = LocalDate.parse(split[1], DatePattern.NORM_DATE_FORMATTER);
                    if (!w.getShiftDay().isBefore(start) && !w.getShiftDay().isAfter(end)) {
                        w.setDateType(weekdayRule.getDateType());
                        w.setWorkState(weekdayRule.getStatus());
                        w.setText(weekdayRule.getText());
                        w.setWeekdayRuleId(weekdayRule.getId());
                    }

                } else if (weekdayRule.getType() == 3) {
                    if (LocalDate.parse(weekdayRule.getValue(), DatePattern.NORM_DATE_FORMATTER).equals(w.getShiftDay())) {
                        w.setDateType(weekdayRule.getDateType());
                        w.setWorkState(weekdayRule.getStatus());
                        w.setText(weekdayRule.getText());
                        w.setWeekdayRuleId(weekdayRule.getId());
                    }
                } else if (weekdayRule.getType() == 2) {
                    String value = weekdayRule.getValue();
                    String[] split = value.split(ProjectConstants.WEEKDAY_RULE_WEEKVALUE_SPLIT);
                    if (split[0].equals(w.getShiftDay().toString()) && split[1].equals(String.valueOf(w.getShiftId()))) {
                        w.setDateType(weekdayRule.getDateType());
                        w.setWorkState(weekdayRule.getStatus());
                        w.setText(weekdayRule.getText());
                        w.setWeekdayRuleId(weekdayRule.getId());
                    }
                }
            }
        }

        return allWeekday;

    }

    public Map<LocalDate, Map<Integer, Integer>> getPlanMap(OrderWorkLoadsReqVo reqVo) {

        Map<LocalDate, Map<Integer, Integer>> stationData = new HashMap<>();

        QueryWrapper<ApsDetailWeekday> query = Wrappers.query();
        query.in("station_id", reqVo.getStationIds());
        query.ge("shift_day", reqVo.getStartDate());
        query.le("shift_day", reqVo.getEndDate());
        query.groupBy("shift_day, station_id");
        List<OrderWorkLoadsDataResVo> resVoList = apsDetailWeekdayMapper.groupByStationSumTotal(query);

        for (OrderWorkLoadsDataResVo owld : resVoList) {
            Map<Integer, Integer> stationMap = stationData.computeIfAbsent(owld.getDay(), e -> new HashMap<>());

            Integer sourcePlanMinutes = stationMap.computeIfAbsent(owld.getStationId(), e -> 0);

            stationMap.put(owld.getStationId(), sourcePlanMinutes + owld.getPlanMinutes());

        }
        return stationData;
    }

    public BaseListResVo<OrderWorkLoadsTreeResVo> workLoadsTree() {
//        List<StationGroup> sgList = stationGroupMapper.lambdaQuery().list();
//        // 先查出工位
//        List<Station> stationList = stationMapper.lambdaQuery().list();
//        Map<Integer, Station> stationMap = stationList.stream().collect(Collectors.toMap(Station::getId, Function.identity()));
//
//        // 再查出工作组
//        List<Group> groupList = groupMapper.lambdaQuery().list();
//        Map<Integer, Group> groupMap = groupList.stream().collect(Collectors.toMap(Group::getId, Function.identity()));
//        List<Group> collect = sgList.stream().map(e -> groupMap.get(e.getGroupId())).distinct().collect(Collectors.toList());
//
//        List<OrderWorkLoadsTreeResVo> data = collect.stream()
//                .map(e -> {
//                    OrderWorkLoadsTreeResVo r = new OrderWorkLoadsTreeResVo();
//                    r.setId(-e.getId());
//                    r.setType(1);
//                    r.setName(e.getName());
//                    r.setPid(null);
//                    return r;
//                }).collect(Collectors.toList());
//
//        // 数据组合
//
//        for (StationGroup stationGroup : sgList) {
//
//            Station station = stationMap.get(stationGroup.getStationId());
//
//            OrderWorkLoadsTreeResVo r = new OrderWorkLoadsTreeResVo();
//            r.setId(station.getId());
//            r.setType(2);
//            r.setName(station.getName());
//            r.setPid(-stationGroup.getGroupId());
//            data.add(r);
//        }
//
//        return new BaseListResVo<>(data);
        return BaseListResVo.empty();
    }

    @Transactional
    public void delete(BaseIdReqVo reqVo) {

        Order o = orderMapper.selectById(reqVo.getId());
        List<Order> orderList = Arrays.asList(o);

//        List<Order> orderList = orderMapper.findMbd();

        for (Order order : orderList) {

            if (order == null) {
                return;
            }

            List<Integer> orderType = Arrays.asList(1, 3, 4);
            if (orderType.contains(order.getOrderType()) && order.getOrderStatus() != 1 && order.getOrderStatus() != 2) {
                throw SyExceptionUtils.e("状态不对，无法删除");
            }

            if (order.getOrderType().equals(2)) {

                ImportMbdOrder oldOrder = importMbdOrderMapper.lambdaQuery()
                        .eq(ImportMbdOrder::getMaterCode, order.getMaterCode())
                        .eq(ImportMbdOrder::getOrderCode, order.getOrderCode())
                        .one();
                if (oldOrder != null) {
                    importMbdOrderMapper.deleteReal(oldOrder.getId());
                    importMbdBomInfoMapper.deleteReal(oldOrder.getId());
                    importMbdPartInfoMapper.deleteReal(oldOrder.getId());
                    importMbdProcessPlanMapper.deleteReal(oldOrder.getId());
                    importMbdOperationMapper.deleteReal(oldOrder.getId());
                }

            }

            orderMapper.deleteReal(order.getId());
            orderBomMapper.deleteReal(order.getId());
            orderPhaseMapper.deleteReal(order.getId());
            orderAccessoriesMapper.deleteReal(order.getId());

            reverseOrderMapper.deleteHard(order.getId());
            reverseDetailMapper.deleteHard(order.getId());
            reverseTopMapper.deleteHard(order.getId());

            mbdBalanceRateMapper.deleteByOrderId(order.getId());
            mbdBalanceRateItemMapper.deleteByOrderId(order.getId());
        }

    }

    @Transactional
    public void externalBomDel(List<Integer> ids) {
        if (CollUtil.isEmpty(ids)) {
            return;
        }

//        Order order = orderMapper.selectById(orderBom.getOrderId());
//        if (order.getOrderStatus() >= 3) {
//            throw SyExceptionUtils.e("节点禁止删除!");
//        }
//
//        if (order.getOrderStatus() >= 8) {
//            throw SyExceptionUtils.e("状态不正确，无法删除");
//        }

        List<OrderBom> orderBomList = orderBomMapper.lambdaQuery().in(OrderBom::getId, ids).list();
        List<Integer> orderIds = orderBomList.stream().map(OrderBom::getOrderId).distinct().collect(Collectors.toList());
        List<Order> orderList = orderMapper.selectBatchIds(orderIds);
        long finishOrderCount = orderList.stream().filter(e -> e.getOrderStatus() >= 9).count();
        if (finishOrderCount > 0) {
            throw SyExceptionUtils.e("订单已完成或者关闭，无法删除");
        }

        List<Integer> bomIdList = orderBomList.stream().map(BaseEntity::getId).distinct().collect(Collectors.toList());
        List<OrderPhase> orderPhaseList = orderPhaseMapper.lambdaQuery().in(OrderPhase::getBomId, bomIdList).list();
        Map<Integer, List<OrderPhase>> orderPhaseBomMap = orderPhaseList.stream().collect(Collectors.groupingBy(OrderPhase::getBomId));

        Map<Integer, Order> orderMap = orderList.stream().collect(Collectors.toMap(BaseEntity::getId, e -> e));

        List<ApsWorkOrder> apsWorkOrderList = apsWorkOrderMapper.lambdaQuery().in(ApsWorkOrder::getBomId, bomIdList).list();

        for (OrderBom bom : orderBomList) {
            Integer count = orderBomMapper.lambdaQuery().eq(OrderBom::getPid, bom.getId()).count();
            if (count > 0) {
                throw SyExceptionUtils.e("有子节点，无法删除");
            }

            if (bom.getPid() == null) {
                throw SyExceptionUtils.e("根节点无法删除");
            }

            orderBomMapper.deleteByBomId(bom.getId());
            orderPhaseMapper.deleteByBomId(bom.getId());

            Order order = orderMap.get(bom.getOrderId());
            if (order.getOrderStatus() < 4) {
                continue;
            }

            if (order.getOrderStatus() < 6) {
                order.setOrderStatus(3);
                orderMapper.updateById(order);
                continue;
            }

            apsWorkOrderMapper.deleteBomId(bom.getId());
            List<OrderPhase> orderPhases = orderPhaseBomMap.get((bom.getId()));
            for (OrderPhase orderPhase : orderPhases) {
                List<ApsWorkDetail> list = apsWorkDetailMapper.lambdaQuery().eq(ApsWorkDetail::getPhaseId, orderPhase.getId()).list();
                if (CollUtil.isNotEmpty(list)) {
                    List<Integer> apsWorkDetailId = list.stream().map(BaseEntity::getId).collect(Collectors.toList());
                    for (Integer workDetailId : apsWorkDetailId) {
                        workDetailTaskMapper.deleteByWorkDetailId(workDetailId);
                    }

                }
                apsWorkDetailMapper.deleteByPhaseId(orderPhase.getId());
                apsDetailWeekdayMapper.deleteByPhaseId(orderPhase.getId());
            }
//            workDetailTaskMapper.deleteByWorkDetailId();
        }

        List<ApsWorkOrder> wlWorkOrderList = apsWorkOrderList.stream().filter(e -> e.getWorkChain().equals("WL")).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(wlWorkOrderList)) {
            // 删除立体库的信息
            List<MesPicking> pickList = wlWorkOrderList.stream().map(e -> {
                MesPicking p = new MesPicking();
                p.setPickListNo(Long.valueOf(e.getPickCode()));
                p.setPickListItemNo(e.getPickSeq());
                return p;
            }).collect(Collectors.toList());
            try {
                Result result = wmsLtkApiClient.deletePickIng(pickList);
                log.info("立体库删除外购件领料单结果：", result);
            } catch (Exception e) {
                log.error("立体库删除外购件领料单异常：", e);
            }
        }
    }

    @Transactional
    public void bomAdd(OrderBomAddReqVo reqVo) {
        OrderBom orderBom = MkBeanUtils.copyProperties(reqVo, OrderBom.class);

        if (reqVo.getReadyType() == null) {
            throw SyExceptionUtils.e("没有备料方式");
        }

        if (reqVo.getPid() == null) {
            throw SyExceptionUtils.e("请选择父节点");
        }

        OrderBom parent = orderBomMapper.selectById(reqVo.getPid());
        Order order = orderMapper.selectById(parent.getOrderId());
        ProcessChain processChain = processChainMapper.selectById(reqVo.getProcessChainId());

        if (!parent.getMaterType().equals("Assembly")) {
            throw SyExceptionUtils.e("父节点不是组件");
        }

        if (orderBom.getMaterType() == null) {
            throw SyExceptionUtils.e("没有物料类型");
        }
        if (orderBom.getMaterType().equals("Platepart") && order.getOrderType().equals(3)) {
            throw SyExceptionUtils.e("外揽订单没有自制件!");
        }

        if (orderBom.getMaterType().equals("Component") || processChain.getMyCode().equals("WL")) {
            orderBom.setWorkChain("WL");
            orderBom.setReadyType(2);
            orderBom.setMaterType("Component");
        } else {
            orderBom.setWorkChain("");
            orderBom.setReadyType(1);
        }

        orderBom.setErpCode(reqVo.getErpCode());// 添加
        orderBom.setMaterCode(orderBom.getPlmId());
        orderBom.setTopFlag(0);
        orderBom.setModifyStatus(LocalDateTime.now().format(DatePattern.PURE_DATETIME_FORMATTER));
        orderBom.setOrderId(parent.getOrderId());
        orderBom.setFactoryNo(parent.getFactoryNo());
        orderBom.setLevel(parent.getLevel() + 1);
        orderBom.setTotalCount(parent.getTotalCount().multiply(orderBom.getPartCount()));
        orderBom.setAssemblyPath(parent.getAssemblyPath() + "/" + orderBom.getMaterCode());
        orderBom.setMaterWeight(reqVo.getWeight());
        orderBom.setMaterHigh(reqVo.getMaterHigh());
        if (!StringUtils.hasText(orderBom.getDrawing())) {
            orderBom.setDrawing(orderBom.getPlmId().replace("_170", ""));
        }

        orderBom.setWorkChain(processChain.getMyCode());
        if (orderBom.getMaterType().equals("Platepart")) {
            orderBom.setStandards(orderBom.getTexture() + "δ" + orderBom.getMaterHigh());
        }

        orderBomMapper.insert(orderBom);

        if (order.getOrderStatus() <= 3 && reqVo.getReadyType().equals(2)) {
            return;
        }

        List<ProcessChainItem> itemList = processChainItemMapper.lambdaQuery().eq(ProcessChainItem::getChainId, reqVo.getProcessChainId()).orderByAsc(ProcessChainItem::getSeq).list();
        List<PhaseGroup> list = phaseGroupMapper.lambdaQuery().in(PhaseGroup::getPhaseCode, itemList.stream().map(ProcessChainItem::getMyCode).distinct().collect(Collectors.toList())).list();
        Map<String, List<PhaseGroup>> phaseGroupMap = list.stream().collect(Collectors.groupingBy(PhaseGroup::getPhaseCode));

        List<OrderPhase> orderPhaseList = itemList.stream()
                .map(e -> {
                    OrderPhase item = new OrderPhase();
                    item.setBomId(orderBom.getId());
                    item.setOrderId(orderBom.getOrderId());
                    item.setWorkChain(orderBom.getWorkChain());
                    item.setPhaseName(e.getName());
                    item.setPhaseCode(e.getMyCode());
                    item.setPhaseSeq(e.getSeq());
                    item.setMaterNo(orderBom.getMaterCode());
                    item.setMaterName(orderBom.getMaterName());
                    if (item.getPhaseCode().equals("FM")) {
                        item.setWorkGroupNumber("4-3_FM_00");
                        item.setWorkTime(0);
                    } else if (item.getPhaseCode().equals("PT")) {
                        item.setWorkGroupNumber("4-3_PTX_00");
                        item.setWorkTime(10 * 60);
                    }

                    if (order.getOrderType().equals(4)) {
                        item.setWorkTime(1);

                        List<PhaseGroup> phaseGroups = phaseGroupMap.get(e.getMyCode());
                        if (CollUtil.isNotEmpty(phaseGroups)) {
                            item.setWorkGroupNumber(phaseGroups.get(0).getGroupCode());
                        }
                    }
                    item.setOriWorkTime(item.getWorkTime());
                    return item;
                })
                .collect(Collectors.toList());
        orderPhaseMapper.insertBatchSomeColumn(orderPhaseList);


        // 将 orderBom 进行写入，如果该条数据的父节点原本为普通节点，则要跟随修改其父节点的类别数据
        OrderPart one = orderPartMapper.lambdaQuery().eq(OrderPart::getPlmId, orderBom.getPlmId()).one();
        if (one == null) {
            OrderPart orderPart = new OrderPart();
            String code = orderBom.getPlmId();
            if (code.endsWith("_170")) {
                code = code.substring(0, code.indexOf("_170"));
            }
            ImportMbdDxf importMbdDxf = importMbdDxfMapper.lambdaQuery().eq(ImportMbdDxf::getPlmid, code).orderByDesc(ImportMbdDxf::getDocVersion).last("limit 1").one();

            orderPart.setPlmId(orderBom.getPlmId());
            // orderPart.setPngUrl(); // 零件PNG图纸路径
            // orderPart.setDxfUrl(); // 零件DXF图纸路径
            orderPart.setDrawing(orderBom.getDrawing());
            if (!Objects.equals(orderBom.getMaterType(), "Platepart")) {
                orderPart.setTexture(orderBom.getTexture());
            } else {
                orderPart.setTexture(orderBom.getTexture());
                orderPart.setThickness(new BigDecimal(orderBom.getMaterHigh()));
            }

            orderPart.setType(2); // 普通件
            orderPart.setNetWeight(orderBom.getMaterWeight());
            orderPart.setWorkChain(orderBom.getWorkChain()); // 工序链
            orderPart.setSource(orderBom.getReadyType()); // 备料方式：1 自制  2 外购
            orderPart.setVersionCode(1L); // 版本号
            orderPart.setMaterType(orderBom.getMaterType()); // 物料类别
            orderPart.setDrawStatus(1); // 是否制图就绪，默认 未就绪
            orderPart.setVersionNum(importMbdDxf != null ? importMbdDxf.getDocVersion() : null); // 图纸版本号
            orderPart.setDrawUpdateTime(null); // 图纸更新时间
            // orderPart.setLength(); // 宽度
            // orderPart.setWidth(); // 长度
            // orderPart.setArea(); // 面积
            // orderPart.setCritical(); // 是否关键件 0不是 1是
            orderPartMapper.insert(orderPart);
            one = orderPart;
        }

        if (order.getOrderStatus() <= 3) {
            return;
        }

        if (order.getOrderStatus() < 6) {
            order.setOrderStatus(3);
            orderMapper.updateById(order);
            return;
        }

        // 生成ApsWorkOrder
        List<ApsOrder> apsOrderList = apsOrderMapper.lambdaQuery().eq(ApsOrder::getOrderId, order.getId()).list();
        List<ApsWorkOrder> apsWorkOrderList = Stream.of(orderBom)
                .map(e -> {
                    ApsWorkOrder workOrder = MkBeanUtils.copyProperties(e, ApsWorkOrder.class);
                    workOrder.setBomId(e.getId());
                    workOrder.setBomPid(e.getPid());
                    workOrder.setId(null);
                    workOrder.setPid(null);
                    workOrder.setStatus(1);
                    workOrder.setFinishCount(new BigDecimal(0));
                    workOrder.setTotalCount(e.getTotalCount());
                    workOrder.setOrderType(order.getOrderType());
                    workOrder.setPlmId(e.getPlmId());
//                    apsBom.setApsOrderId(apsOrder.getId());
//                    apsBom.setOrderCount(e.getTotalCount().multiply(new BigDecimal(apsOrder.getOrderQty())));
                    return workOrder;
                })
                .flatMap(e ->
                        apsOrderList
                                .stream()
                                .map(e1 -> {
                                    ApsWorkOrder awo = new ApsWorkOrder();
                                    BeanUtils.copyProperties(e, awo);
                                    awo.setApsOrderId(e1.getId());
                                    awo.setOrderCount(e.getTotalCount().multiply(new BigDecimal(e1.getOrderQty())));
                                    awo.setPlanStartDateTime(LocalDateTime.now());
                                    awo.setPlanEndDateTime(LocalDateTime.now());
                                    return awo;
                                })
                )
                .collect(Collectors.toList());
        apsWorkOrderMapper.insertBatch(apsWorkOrderList);

        // 状态大于等于6时，需要判断该件是自制还是外购，如果是外购则推送到立体库。
        if (!orderBom.getWorkChain().equals("WL")) {
            return;
        }

        // 把 apsWorkOrderList 赋值，并推送到立体库
        wmsService.partProcurement(order.getId(), 0);


    }

    private void outScheduleOrder(Order order, OrderBom parent, OrderBom orderBom, List<OrderPhase> orderPhases) {
        ApsOrder one = apsOrderMapper.lambdaQuery().eq(ApsOrder::getOrderId, order.getId()).last("limit 1").one();
        Assert.notNull(one, String.format("APS 订单 %s 不存在", order.getOrderCode()));
        Assert.isTrue(one.getOrderType() == 3, String.format("订单 %s 不是外揽订单", order.getOrderCode()));
        // 对于外揽订单，标记订单为已开工
        order.setOrderStatus(8);
        // 生成工单
        outScheduleAddPhase(order, one, parent, orderBom, orderPhases);
    }

    private void outScheduleAddPhase(Order order, ApsOrder one, OrderBom parent, OrderBom orderBom, List<OrderPhase> orderPhases) {
        orderPhases.forEach(e -> outScheduleAddPhase(order, one, parent, orderBom, orderPhases, e));
    }

    @Transactional
    public void phaseAdd(OrderPhaseAddReqVo reqVo) {
        OrderPhase orderPhase = MkBeanUtils.copyProperties(reqVo, OrderPhase.class);
        Phase phase = phaseMapper.selectById(reqVo.getPhaseId());
        OrderBom bom = orderBomMapper.selectById(reqVo.getBomId());
        Group group = groupMapper.selectById(reqVo.getGroupId());
        List<OrderPhase> phaseList = orderPhaseMapper.lambdaQuery()
                .eq(OrderPhase::getBomId, bom.getId())
                .orderByAsc(OrderPhase::getPhaseSeq)
                .list();

        int index = 0;
        List<String> workChaineList = new ArrayList<>();
        if (CollUtil.isNotEmpty(phaseList)) {
            index = phaseList.get(phaseList.size() - 1).getPhaseSeq();
            workChaineList.addAll(phaseList.stream().map(OrderPhase::getPhaseCode).collect(Collectors.toList()));
        }
        workChaineList.add(phase.getMyCode());
        String workChain = String.join("-", workChaineList);
        bom.setWorkChain(workChain);
        orderBomMapper.updateById(bom);

        index++;
        orderPhase.setOrderId(bom.getOrderId());
        orderPhase.setBomId(bom.getId());
        orderPhase.setWorkChain(bom.getWorkChain());
        orderPhase.setPhaseName(phase.getName());
        orderPhase.setPhaseCode(phase.getMyCode());
        orderPhase.setMaterNo(bom.getMaterCode());
        orderPhase.setMaterName(bom.getMaterName());
        orderPhase.setWorkGroupNumber(group.getMyCode());
        orderPhase.setPhaseSeq(index);
        orderPhaseMapper.insert(orderPhase);

        for (OrderPhase orderPhase1 : phaseList) {
            orderPhase1.setWorkChain(workChain);
            orderPhaseMapper.updateById(orderPhase1);
        }
        phaseList.add(orderPhase);
        Order order = orderMapper.selectById(bom.getOrderId());

        if (order.getOrderStatus() >= 9) {
            throw SyExceptionUtils.e("订单完成，禁止添加工序");
        }

        if (order.getOrderStatus() <= 0) {
            throw SyExceptionUtils.e("订单未同步，禁止添加工序");
        }

        if (order.getOrderStatus() == 1) {
            return;
        }

        if (order.getOrderStatus() == 2 || order.getOrderStatus() == 3 || order.getOrderStatus() == 5) {

            if (order.getOrderStatus() == 5) {
                order.setOrderStatus(3);
                orderMapper.updateById(order);
            }

            ReverseOrder root = reverseOrderMapper.lambdaQuery()
                    .eq(ReverseOrder::getOrderId, order.getId())
                    .isNull(ReverseOrder::getParentId)
                    .one();
            if (root == null) {
                throw SyExceptionUtils.e("订单异常");
            }

            List<ReverseOrder> children = reverseOrderMapper.lambdaQuery()
                    .eq(ReverseOrder::getOrderId, order.getId())
                    .in(ReverseOrder::getParentId, root.getId())
                    .orderByAsc(ReverseOrder::getSplitNum)
                    .list();

            reverseOrderMapper.insertBatchSomeColumn(children);
            // 倒序排产
            reverseDetailMapper.deleteHard(order.getId());
            reverseAllScheduling(order, root, children);

            root.setPlanStartDateTime(children.stream().min(Comparator.comparing(ReverseOrder::getPlanStartDateTime)).orElseGet(ReverseOrder::new).getPlanStartDateTime());
            root.setPlanEndDateTime(children.stream().max(Comparator.comparing(ReverseOrder::getPlanEndDateTime)).orElseGet(ReverseOrder::new).getPlanEndDateTime());
            reverseOrderMapper.updateById(root);
            return;
        }

        if (order.getOrderStatus() == 4) {
            throw SyExceptionUtils.e("有订单正在排产，请稍后再操作");
        }


        List<ReverseOrder> children = reverseOrderMapper.lambdaQuery()
                .eq(ReverseOrder::getOrderId, order.getId())
                .isNotNull(ReverseOrder::getParentId)
                .list();
//        List<StationGroup> stationGroupList = stationGroupMapper.lambdaQuery().eq(StationGroup::getGroupId, group.getId()).list();
//        List<Station> stationList = stationMapper.selectBatchIds(stationGroupList.stream().map(StationGroup::getStationId).collect(Collectors.toList()));
        List<Station> stationList = stationMapper.lambdaQuery().eq(Station::getGroupId, group.getId()).list();
        for (ReverseOrder child : children) {
            ReverseDetail rd = new ReverseDetail();
            rd.setPhaseSeq(orderPhase.getPhaseSeq());
            rd.setPhaseId(orderPhase.getId());
            rd.setReverseOrderId(child.getId());
            rd.setOrderId(child.getOrderId());
            rd.setBomId(bom.getId());
            rd.setBomPid(bom.getPid());
            rd.setGroupCode(orderPhase.getWorkGroupNumber());
            rd.setPlanStartSecond(0);
            rd.setLevel(bom.getLevel());
            rd.setStationGroupId(null);

            rd.setGroupId(group.getId());

            // 取出这个工序的真实的工作秒数
            rd.setWorkCount(stationList.size());
            rd.setWorkAbility(stationList.get(0).getWorkAbility());
            rd.setWorkTime(orderPhase.getWorkTime());
            rd.setTotalCount(null);

            rd.setSplitNum(null);

            rd.setProcessSecond(bom.getTotalCount()
                    .multiply(new BigDecimal(orderPhase.getWorkTime()))
                    .setScale(0, RoundingMode.UP)
                    .intValue());

            rd.setPlanEndSecond(rd.getPlanStartSecond() + rd.getProcessSecond());
            rd.setAppendFlag(2);
            reverseDetailMapper.insert(rd);
        }


        List<ApsWorkOrder> awoList = apsWorkOrderMapper.lambdaQuery()
                .eq(ApsWorkOrder::getOrderId, order.getId())
                .eq(ApsWorkOrder::getBomId, bom.getId())
                .list();

        if (awoList.isEmpty()) {
            List<ApsWorkOrder> parentList = apsWorkOrderMapper.lambdaQuery()
                    .eq(ApsWorkOrder::getOrderId, order.getId())
                    .eq(ApsWorkOrder::getBomId, bom.getPid())
                    .list();

            List<ApsOrder> apsOrders = apsOrderMapper.selectBatchIds(parentList.stream().map(ApsWorkOrder::getApsOrderId).collect(Collectors.toList()));
            Map<Integer, ApsOrder> collect = apsOrders.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

            for (ApsWorkOrder apsWorkOrder : parentList) {

                LocalDateTime endDateTime = apsWorkOrder.getPlanStartDateTime();
                ApsWorkOrder workOrder = MkBeanUtils.copyProperties(bom, ApsWorkOrder.class);

                workOrder.setApsOrderId(collect.get(apsWorkOrder.getApsOrderId()).getId());
                workOrder.setBomId(bom.getId());
                workOrder.setBomPid(bom.getPid());
                workOrder.setId(null);
                workOrder.setPid(apsWorkOrder.getId());
                workOrder.setStatus(2);
                workOrder.setFinishCount(new BigDecimal(0));
                workOrder.setTotalCount(bom.getTotalCount());
                workOrder.setOrderCount(bom.getTotalCount().multiply(new BigDecimal(collect.get(apsWorkOrder.getApsOrderId()).getOrderQty())));
                workOrder.setOrderType(order.getOrderType());
                workOrder.setPlanStartDateTime(endDateTime);
                workOrder.setPlanEndDateTime(endDateTime);
                workOrder.setAppendFlag(2);

                apsWorkOrderMapper.insert(workOrder);
                awoList.add(workOrder);
            }
        }

        // 判断有多少包
        // 判断上级节点的时间
        Integer smallTransfer = stationList.get(0).getSmallTransfer() == null ? 0 : stationList.get(0).getSmallTransfer();

        List<ApsWorkDetail> apsWorkDetails = new ArrayList<>();

        for (ApsWorkOrder workOrder : awoList) {

            ApsOrder apsOrder = apsOrderMapper.selectById(workOrder.getApsOrderId());

            ReverseDetail rd = new ReverseDetail();
            rd.setPhaseSeq(orderPhase.getPhaseSeq());
            rd.setPhaseId(orderPhase.getId());
            rd.setReverseOrderId(apsOrder.getReverseId());
            rd.setOrderId(workOrder.getOrderId());
            rd.setBomId(bom.getId());
            rd.setBomPid(bom.getPid());
            rd.setGroupCode(orderPhase.getWorkGroupNumber());
            rd.setPlanStartSecond(0);
            rd.setLevel(bom.getLevel());
            rd.setStationGroupId(null);

            rd.setGroupId(group.getId());

            // 取出这个工序的真实的工作秒数
            rd.setWorkCount(stationList.size());
            rd.setWorkAbility(stationList.get(0).getWorkAbility());
            rd.setWorkTime(orderPhase.getWorkTime());
            rd.setTotalCount(null);

            rd.setSplitNum(null);

            rd.setProcessSecond(bom.getTotalCount()
                    .multiply(new BigDecimal(orderPhase.getWorkTime()))
                    .setScale(0, RoundingMode.UP)
                    .intValue());

            rd.setPlanEndSecond(rd.getPlanStartSecond() + rd.getProcessSecond());
            rd.setAppendFlag(2);
            reverseDetailMapper.insert(rd);


            ApsWorkDetail apsWorkDetail = new ApsWorkDetail();
            apsWorkDetail.setOrderId(order.getId());
            apsWorkDetail.setApsOrderId(workOrder.getApsOrderId());
            apsWorkDetail.setApsWorkOrderId(workOrder.getId());
            apsWorkDetail.setApsWorkOrderPid(workOrder.getPid());


            if (projectConfig.getIgnorePhaseCodeList().contains(orderPhase.getPhaseCode())) {
                continue;
            }

            apsWorkDetail.setPhaseId(orderPhase.getId());
            apsWorkDetail.setWorkTime(orderPhase.getWorkTime());

            apsWorkDetail.setPhaseSeq(orderPhase.getPhaseSeq());
            apsWorkDetail.setPhaseCode(orderPhase.getPhaseCode());
            apsWorkDetail.setPhaseName(orderPhase.getPhaseName());
            apsWorkDetail.setPhaseCode(orderPhase.getPhaseCode());
            apsWorkDetail.setMaterNo(orderPhase.getMaterNo());
            apsWorkDetail.setMaterName(orderPhase.getMaterName());
            apsWorkDetail.setGroupCode(orderPhase.getWorkGroupNumber());
            apsWorkDetail.setOrderType(order.getOrderType());

            // 从倒排表里取
            apsWorkDetail.setPartCount(bom.getPartCount());
            apsWorkDetail.setTotalCount(workOrder.getOrderCount());
            apsWorkDetail.setGroupId(group.getId());
            apsWorkDetail.setProcessCount(new BigDecimal(0));
            apsWorkDetail.setFinishCount(new BigDecimal(0));
            apsWorkDetail.setStatus(1);
//                apsWorkDetail.setStationGroupId(e.getStationGroupId());

            apsWorkDetail.setDetailSeq(null);
            apsWorkDetail.setApsOrderId(workOrder.getApsOrderId());
            apsWorkDetail.setReverseDetailId(rd.getId());
            apsWorkDetail.setAppendFlag(2);
            apsWorkDetail.setPlanStartDateTime(workOrder.getPlanStartDateTime().minusSeconds(orderPhase.getWorkTime()));
            apsWorkDetail.setPlanEndDateTime(workOrder.getPlanEndDateTime().minusSeconds(orderPhase.getWorkTime()));
            apsWorkDetails.add(apsWorkDetail);

        }

        List<ApsWorkDetail> collect = apsWorkDetails.stream()
                .flatMap(e -> {

                    if (CollUtil.isEmpty(stationList)) {
                        throw SyExceptionUtils.e("{}没有工位", e.getGroupCode());
                    }
                    if (smallTransfer == null || smallTransfer <= 0) {
                        return Stream.of(e);
                    }

                    int div = e.getTotalCount().divide(new BigDecimal(smallTransfer), 0, RoundingMode.DOWN).intValue();

                    BigDecimal subtract = e.getTotalCount().subtract(new BigDecimal(smallTransfer).multiply(new BigDecimal(div)));


                    List<ApsWorkDetail> l = new ArrayList<>();

                    for (int i = 0; i < div; i++) {
                        ApsWorkDetail apsWorkDetail = MkBeanUtils.copyProperties(e, ApsWorkDetail.class);
                        apsWorkDetail.setTotalCount(new BigDecimal(smallTransfer));
                        l.add(apsWorkDetail);
                    }

                    if (subtract.compareTo(BigDecimal.ZERO) > 0) {
                        ApsWorkDetail apsWorkDetail = MkBeanUtils.copyProperties(e, ApsWorkDetail.class);
                        apsWorkDetail.setTotalCount(subtract);
                        l.add(apsWorkDetail);
                    }

                    return l.stream();

                })
                .collect(Collectors.toList());

        for (ApsWorkDetail apsWorkDetail : collect) {
            apsWorkDetail.setType(2);
            apsWorkDetailMapper.insert(apsWorkDetail);
        }


//        Integer smallTransfer = stationList.get(0).getSmallTransfer() == null ? 0 : stationList.get(0).getSmallTransfer();


//        List<StationGroup> stationGroupList = stationGroupMapper.lambdaQuery().eq(StationGroup::getGroupId, group.getId()).list();
        // 如果是激割或者火割，则推送套料
        List<String> splitPhaseList = Arrays.asList("JG", "HG");
        if (order.getOrderStatus() >= 6 && splitPhaseList.contains(orderPhase.getPhaseCode())) {

            for (ApsWorkDetail apsWorkDetail : collect) {

                Map<Integer, ApsWorkOrder> workOrderMap = awoList.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));
                ApsWorkOrder apsWorkOrder = workOrderMap.get(apsWorkDetail.getApsWorkOrderId());

                List<ImportMbdDxf> importMbdDxfList = importMbdDxfMapper.lambdaQuery().in(ImportMbdDxf::getPlmid, bom.getPlmId()).list();
                Map<String, ImportMbdDxf> mbdDxfMap = importMbdDxfList.stream().collect(Collectors.toMap(ImportMbdDxf::getPlmid, Function.identity(), (a, b) -> b));

                List<PlateStandard> plateStandardList = plateStandardMapper.lambdaQuery().in(PlateStandard::getNorm, apsWorkOrder.getStandards()).list();
                Map<String, List<PlateStandard>> plateStandardMap = plateStandardList.stream().collect(Collectors.groupingBy(PlateStandard::getNorm));


                hexagonNestOldUtils.saveDraw(apsWorkOrder, order, bom, mbdDxfMap);

                ApsWorkOrder pa = apsWorkOrderMapper.selectById(apsWorkOrder.getPid());
                ApsOrder apsOrder = apsOrderMapper.selectById(pa.getApsOrderId());
                hexagonNestOldUtils.savePlan(apsWorkDetail, order, apsOrder, apsWorkOrder, pa, plateStandardMap, mbdDxfMap);

            }
            order.setPushStatus(4);
            orderMapper.updateById(order);
        }
    }

    private void outScheduleAddPhase(Order order, ApsOrder apsOrder, OrderBom parent, OrderBom bom, List<OrderPhase> phaseList, OrderPhase orderPhase) {
        // 查询工单
        ApsWorkOrder workOrder = apsWorkOrderMapper.lambdaQuery()
                .eq(ApsWorkOrder::getBomId, bom.getId())
                .one();
        ApsWorkOrder parentWorkOrder = apsWorkOrderMapper.lambdaQuery()
                .eq(ApsWorkOrder::getBomId, parent.getId())
                .one();
        // 工单不存在，则创建工单
        if (workOrder == null) {
            workOrder = MkBeanUtils.copyProperties(bom, ApsWorkOrder.class);
            workOrder.setApsOrderId(apsOrder.getId());
            workOrder.setBomId(bom.getId());
            workOrder.setBomPid(bom.getPid());
            workOrder.setId(null);
            workOrder.setPid(parentWorkOrder.getId());
            workOrder.setStatus(2); //初始化为开工中
            workOrder.setFinishCount(new BigDecimal(0));
            workOrder.setTotalCount(bom.getTotalCount());
            workOrder.setOrderCount(bom.getTotalCount());
            workOrder.setOrderType(3); // 手动录入
            workOrder.setWorkChain(bom.getWorkChain());
            workOrder.setPlanStartDateTime(LocalDateTime.now());
            workOrder.setPlanEndDateTime(LocalDateTime.now().plusSeconds(1));
            workOrder.setAppendFlag(2);
            apsWorkOrderMapper.insert(workOrder);
            // 同步工件信息到mbd
            TbSizeInfoDto sizeInfoDto = new TbSizeInfoDto();
            sizeInfoDto.setPlmid(bom.getPlmId());
            sizeInfoDto.setPartName(bom.getMaterCode());
            if (bom.getMaterWeight() != null) {
                sizeInfoDto.setWeight(bom.getMaterWeight().doubleValue());
            }
            if (bom.getMaterHigh() != null) {
                sizeInfoDto.setThickness(bom.getMaterHigh().doubleValue());
            }
            momSrvMbdApiClient.insertNewPartSize(sizeInfoDto);
        } else {
            // 更新工单工序链
            apsWorkOrderMapper.lambdaUpdate()
                    .set(ApsWorkOrder::getWorkChain, bom.getWorkChain())
                    .eq(ApsWorkOrder::getId, workOrder.getId())
                    .update();
        }
        // 创建工单明细
        List<Group> groups = groupMapper.lambdaQuery()
                .in(Group::getMyCode, orderPhase.getWorkGroupNumber())
                .list();
        if (groups.isEmpty()) {
            throw SyExceptionUtils.e("工作组不存在" + orderPhase.getWorkGroupNumber());
        }
        Group group = groups.get(0);
        List<Station> stations = stationMapper.lambdaQuery().eq(Station::getGroupId, group.getId()).list();
//        List<StationGroup> stationGroups = stationGroupMapper.lambdaQuery()
//                .eq(StationGroup::getGroupId, group.getId())
//                .list();
//        if (stationGroups.isEmpty()) {
//            throw SyExceptionUtils.e("工作组未与工位关联" + orderPhase.getWorkGroupNumber());
//        }
        boolean isFirstPhase = orderPhase.getPhaseSeq() == 1;
//        StationGroup stationGroup = stationGroups.get(0);
        Station station = stations.get(0);
        for (int index = 0; index < workOrder.getPartCount().intValue(); index++) {
            ApsWorkDetail apsWorkDetail = new ApsWorkDetail();
            apsWorkDetail.setOrderId(orderPhase.getOrderId());
            apsWorkDetail.setApsOrderId(apsOrder.getId());
            apsWorkDetail.setPhaseId(orderPhase.getId());
            apsWorkDetail.setApsWorkOrderId(workOrder.getId());
            apsWorkDetail.setApsWorkOrderPid(workOrder.getPid());
//            apsWorkDetail.setStationGroupId(stationGroup.getId());
            apsWorkDetail.setStationId(station.getId());
            apsWorkDetail.setGroupId(group.getId());
            apsWorkDetail.setWorkTime(orderPhase.getWorkTime());
            apsWorkDetail.setPhaseSeq(orderPhase.getPhaseSeq());
            apsWorkDetail.setPhaseCode(orderPhase.getPhaseCode());
            apsWorkDetail.setPhaseName(orderPhase.getPhaseName());
            apsWorkDetail.setPhaseCode(orderPhase.getPhaseCode());
            apsWorkDetail.setMaterNo(orderPhase.getMaterNo());
            apsWorkDetail.setMaterName(orderPhase.getMaterName());
            apsWorkDetail.setGroupCode(orderPhase.getWorkGroupNumber());
            apsWorkDetail.setOrderType(workOrder.getOrderType());
            apsWorkDetail.setPartCount(BigDecimal.valueOf(1));
            apsWorkDetail.setTotalCount(BigDecimal.valueOf(1));
            apsWorkDetail.setWorkTime(1);
            apsWorkDetail.setChangTime(0);
            apsWorkDetail.setEnterTime(0);
            apsWorkDetail.setOutTime(0);
            apsWorkDetail.setTotalWorkTime(1);
            apsWorkDetail.setProcessCount(new BigDecimal(0));
            apsWorkDetail.setFinishCount(new BigDecimal(0));
            apsWorkDetail.setStatus(2);
            apsWorkDetail.setDetailSeq(orderPhase.getPhaseSeq());
            apsWorkDetail.setReverseDetailId(null);
            apsWorkDetail.setPlanStartDateTime(LocalDateTime.now());
            apsWorkDetail.setPlanEndDateTime(LocalDateTime.now().plusDays(1));
            apsWorkDetail.setAppendFlag(3); // 从排程中脱离
            apsWorkDetail.setType(2);
            apsWorkDetail.setPlmId(bom.getPlmId());
            apsWorkDetailMapper.insert(apsWorkDetail);
            if (apsWorkDetail.getPhaseCode().equals("FM") && isFirstPhase) {
                partUtilService.makeWorkDetailTask(apsWorkDetail, BigDecimal.ONE, null, null);
            }
        }

    }

    public void reverseAllScheduling(Order order, ReverseOrder root, List<ReverseOrder> children) {

        // 构建缓存数据
        ReverseFactoryCache factoryCache = createFactoryCache(order);

        // 对每个分包进行排产
        for (ReverseOrder child : children) {
            ReverseOrderCache orderCache = createOrderCache(order, root, child);
            List<ReverseDetail> reverseDetails = reverseAllScheduling(factoryCache, orderCache);

            // 把分钟按天分隔
            List<ReverseDetail> dayDetails = dayDetails(child, reverseDetails);
            reverseDetailMapper.insertBatchSomeColumn(dayDetails);

            child.setPlanEndDateTime(dayDetails.stream().max(Comparator.comparing(ReverseDetail::getReverseStartTime)).orElseGet(ReverseDetail::new).getReverseStartTime());
            child.setPlanStartDateTime(dayDetails.stream().min(Comparator.comparing(ReverseDetail::getReverseEndTime)).orElseGet(ReverseDetail::new).getReverseEndTime());
            reverseOrderMapper.updateById(child);
        }

    }


    private List<ReverseDetail> reverseAllScheduling(ReverseFactoryCache factoryCache, ReverseOrderCache orderCache) {

        orderCache.getOrderBomList().sort(Comparator.comparing(OrderBom::getLevel));
        List<OrderBom> orderBomList = orderCache.getOrderBomList();

        Map<Integer, OrderBom> orderBomIdMap = orderBomList.stream().collect(Collectors.toMap(OrderBom::getId, Function.identity()));
        for (OrderPhase orderPhase : orderCache.getOrderPhaseList()) {
            if (orderPhase.getPhaseSeq() == null) {
                throw SyExceptionUtils.e("没有配置工序顺序");
            }

            if (!StringUtils.hasText(orderPhase.getWorkGroupNumber())) {
                throw SyExceptionUtils.e(orderPhase.getMaterName() + "没有配置工作组");
            }

            if (orderPhase.getWorkTime() == null) {
                throw SyExceptionUtils.e(orderPhase.getMaterName() + "没有配置工时");
            }
        }

        Map<Integer, List<OrderPhase>> bomIdPhaseMap = orderCache.getOrderPhaseList()
                .stream()
                .sorted(Comparator.comparing(OrderPhase::getPhaseSeq))
                .collect(Collectors.groupingBy(OrderPhase::getBomId));

        Map<Integer, Map<Integer, ReverseDetail>> bomIdPhaseSeqMap = new LinkedHashMap<>();

        for (OrderBom orderBom : orderBomList) {
            List<OrderPhase> orderPhaseList = bomIdPhaseMap.get(orderBom.getId());
            if (orderPhaseList == null || orderPhaseList.isEmpty()) {
                continue;
            }

            // 反向计算工序时间
            int startSecond = 0;
            for (int i = orderPhaseList.size() - 1; i >= 0; i--) {
                // 是否是最开始的工序
                if (i == orderPhaseList.size() - 1) {
                    // 取父节点的
                    OrderBom parentBom = orderBomIdMap.get(orderBom.getPid());
                    if (parentBom != null) {
                        Map<Integer, ReverseDetail> map = bomIdPhaseSeqMap.get(parentBom.getId());

                        if (CollUtil.isEmpty(map)) {
                            throw SyExceptionUtils.e("零件[{}], 物料号[{}]没有找到父节点零件[{}], 物料号[{}]的工序", orderBom.getMaterName(), orderBom.getMaterCode(), parentBom.getMaterName(), parentBom.getMaterCode());
                        }

                        ReverseDetail reversePhase = map.get(1);
                        startSecond = reversePhase.getPlanEndSecond();
                    }

                } else {
                    // 取前一道工序
                    ReverseDetail reversePhase = bomIdPhaseSeqMap.get(orderPhaseList.get(i).getBomId()).get(orderPhaseList.get(i).getPhaseSeq() + 1);
                    startSecond = reversePhase.getPlanEndSecond();
                }

                ReverseDetail phase = new ReverseDetail();
                phase.setPhaseSeq(orderPhaseList.get(i).getPhaseSeq());
                phase.setPhaseId(orderPhaseList.get(i).getId());
                phase.setReverseOrderId(orderCache.getReverseOrder().getId());
                phase.setOrderId(orderCache.getReverseOrder().getOrderId());
                phase.setBomId(orderBom.getId());
                phase.setBomPid(orderBom.getPid());
                phase.setGroupCode(orderPhaseList.get(i).getWorkGroupNumber());
                phase.setPlanStartSecond(startSecond);
                phase.setLevel(orderBom.getLevel());

                bomIdPhaseSeqMap.computeIfAbsent(orderPhaseList.get(i).getBomId(), k -> new LinkedHashMap<>()).put(phase.getPhaseSeq(), phase);

                ReverseWorkCenter stationList = factoryCache.getWorkCenterMap().get(orderPhaseList.get(i).getWorkGroupNumber());
                if (stationList == null) {
                    throw SyExceptionUtils.e("零件[{}], 物料号[{}]没有找到工作组[{}],或者该工作组下没有工位", orderBom.getMaterName(), orderBom.getMaterCode(), orderPhaseList.get(i).getWorkGroupNumber());
                }

                phase.setStationGroupId(stationList.getStationGroupId());

                phase.setGroupId(stationList.getGroupId());

                // 取出这个工序的真实的工作秒数
                phase.setWorkCount(stationList.getGroupList().size());
                phase.setWorkAbility(stationList.getWorkAbility());
                phase.setWorkTime(orderPhaseList.get(i).getWorkTime());
                phase.setTotalCount(orderBomIdMap.get(orderBom.getId()).getTotalCount());

                phase.setSplitNum(orderCache.getReverseOrder().getSplitNum());

                phase.setProcessSecond(phase.getTotalCount()
                        .multiply(new BigDecimal(phase.getWorkTime()))
                        .divide(phase.getWorkAbility(), 5, RoundingMode.UP)
                        .setScale(0, RoundingMode.UP)
                        .intValue());

                phase.setPlanEndSecond(phase.getPlanStartSecond() + phase.getProcessSecond());

            }

        }

        /*


        Map<Integer, OrderBom> orderBomIdMap = orderBomList.stream().collect(Collectors.toMap(OrderBom::getId, Function.identity()));
        Map<Integer, Map<Integer, ReverseDetail>> bomIdPhaseSeqMap = new LinkedHashMap<>();
        Map<String, List<Station>> groupNumberStationMap = new HashMap<>();
//        Map<String, Group> myCodeGroupMap = factoryCache.getGroupList().stream().collect(Collectors.toMap(Group::getMyCode, Function.identity()));
        if (!factoryCache.getGroupList().isEmpty()) {
            List<Group> groupList = factoryCache.getGroupList();
            Map<Integer, List<StationGroup>> stationGroupMap = factoryCache.getStationGroupList().stream().filter(e -> e.getDefaultGroup().equals(1)).collect(Collectors.groupingBy(StationGroup::getGroupId));
            Map<Integer, Station> stationMap = factoryCache.getStationList().stream().collect(Collectors.toMap(Station::getId, Function.identity()));
            for (Group group : groupList) {
                List<StationGroup> stationGroups = stationGroupMap.get(group.getId());
                if (stationGroups == null || stationGroups.isEmpty()) {
                    continue;
                }

                List<Station> stations = stationGroups.stream().map(e -> stationMap.get(e.getStationId())).collect(Collectors.toList());
                groupNumberStationMap.put(group.getMyCode(), stations);
            }
        }

        // 排序后的每个零件

        return bomIdPhaseSeqMap.values().stream().flatMap(entry -> entry.values().stream()).sorted(Comparator.comparing(ReverseDetail::getPlanStartSecond)).collect(Collectors.toList());

         */

        return bomIdPhaseSeqMap.values().stream().flatMap(entry -> entry.values().stream()).sorted(Comparator.comparing(ReverseDetail::getPlanStartSecond)).collect(Collectors.toList());
    }


//    public List<ReverseDetail> reverseAllScheduling(ReverseFactoryCache factoryCache, ReverseOrderCache orderCache) {
//
//        orderCache.getOrderBomList().sort(Comparator.comparing(OrderBom::getLevel));
//        List<OrderBom> orderBomList = orderCache.getOrderBomList();
//
//        Map<Integer, OrderBom> orderBomIdMap = orderBomList.stream().collect(Collectors.toMap(OrderBom::getId, Function.identity()));
//
//        Map<Integer, List<OrderPhase>> bomIdPhaseMap = orderCache.getOrderPhaseList()
//                .stream()
//                .sorted(Comparator.comparing(OrderPhase::getPhaseSeq))
//                .collect(Collectors.groupingBy(OrderPhase::getBomId));
//
//        Map<Integer, Map<Integer, ReverseDetail>> bomIdPhaseSeqMap = new LinkedHashMap<>();
//
//        for (OrderBom orderBom : orderBomList) {
//            List<OrderPhase> orderPhaseList = bomIdPhaseMap.get(orderBom.getId());
//            if (orderPhaseList == null || orderPhaseList.isEmpty()) {
//                continue;
//            }
//
//            // 反向计算工序时间
//            int startSecond = 0;
//            for (int i = orderPhaseList.size() - 1; i >= 0; i--) {
//                // 是否是最开始的工序
//                if (i == orderPhaseList.size() - 1) {
//                    // 取父节点的
//                    OrderBom parentBom = orderBomIdMap.get(orderBom.getPid());
//                    if (parentBom != null) {
//                        Map<Integer, ReverseDetail> map = bomIdPhaseSeqMap.get(parentBom.getId());
//
//                        if (CollUtil.isEmpty(map)) {
//                            throw SyExceptionUtils.e("零件[{}], 物料号[{}]没有找到父节点零件[{}], 物料号[{}]的工序", orderBom.getMaterName(), orderBom.getMaterCode(), parentBom.getMaterName(), parentBom.getMaterCode());
//                        }
//
//                        ReverseDetail reversePhase = map.get(1);
//                        startSecond = reversePhase.getPlanEndSecond();
//                    }
//
//                } else {
//                    // 取前一道工序
//                    ReverseDetail reversePhase = bomIdPhaseSeqMap.get(orderPhaseList.get(i).getBomId()).get(orderPhaseList.get(i).getPhaseSeq() + 1);
//                    startSecond = reversePhase.getPlanEndSecond();
//                }
//
//                ReverseDetail phase = new ReverseDetail();
//                phase.setPhaseSeq(orderPhaseList.get(i).getPhaseSeq());
//                phase.setPhaseId(orderPhaseList.get(i).getId());
//                phase.setReverseOrderId(orderCache.getReverseOrder().getId());
//                phase.setOrderId(orderCache.getReverseOrder().getOrderId());
//                phase.setBomId(orderBom.getId());
//                phase.setBomPid(orderBom.getPid());
//                phase.setGroupCode(orderPhaseList.get(i).getWorkGroupNumber());
//                phase.setPlanStartSecond(startSecond);
//                phase.setLevel(orderBom.getLevel());
//
//                bomIdPhaseSeqMap.computeIfAbsent(orderPhaseList.get(i).getBomId(), k -> new LinkedHashMap<>()).put(phase.getPhaseSeq(), phase);
//
//                ReverseWorkCenter stationList = factoryCache.getWorkCenterMap().get(orderPhaseList.get(i).getWorkGroupNumber());
//                if (stationList == null) {
//                    throw SyExceptionUtils.e("零件[{}], 物料号[{}]没有找到工作组[{}],或者该工作组下没有工位", orderBom.getMaterName(), orderBom.getMaterCode(), orderPhaseList.get(i).getWorkGroupNumber());
//                }
//
//                phase.setStationGroupId(stationList.getStationGroupId());
//
//                phase.setGroupId(stationList.getGroupId());
//
//                // 取出这个工序的真实的工作秒数
//                phase.setWorkCount(stationList.getGroupList().size());
//                phase.setWorkAbility(stationList.getWorkAbility());
//                phase.setWorkTime(orderPhaseList.get(i).getWorkTime());
//                phase.setTotalCount(orderBomIdMap.get(orderBom.getId()).getTotalCount());
//
//                phase.setSplitNum(orderCache.getReverseOrder().getSplitNum());
//
//                phase.setProcessSecond(phase.getTotalCount()
//                        .multiply(new BigDecimal(phase.getWorkTime()))
//                        .divide(phase.getWorkAbility(), 5, RoundingMode.UP)
//                        .setScale(0, RoundingMode.UP)
//                        .intValue());
//
//                phase.setPlanEndSecond(phase.getPlanStartSecond() + phase.getProcessSecond());
//
//            }
//
//        }
//
//        /*
//
//
//        Map<Integer, OrderBom> orderBomIdMap = orderBomList.stream().collect(Collectors.toMap(OrderBom::getId, Function.identity()));
//        Map<Integer, Map<Integer, ReverseDetail>> bomIdPhaseSeqMap = new LinkedHashMap<>();
//        Map<String, List<Station>> groupNumberStationMap = new HashMap<>();

    /// /        Map<String, Group> myCodeGroupMap = factoryCache.getGroupList().stream().collect(Collectors.toMap(Group::getMyCode, Function.identity()));
//        if (!factoryCache.getGroupList().isEmpty()) {
//            List<Group> groupList = factoryCache.getGroupList();
//            Map<Integer, List<StationGroup>> stationGroupMap = factoryCache.getStationGroupList().stream().filter(e -> e.getDefaultGroup().equals(1)).collect(Collectors.groupingBy(StationGroup::getGroupId));
//            Map<Integer, Station> stationMap = factoryCache.getStationList().stream().collect(Collectors.toMap(Station::getId, Function.identity()));
//            for (Group group : groupList) {
//                List<StationGroup> stationGroups = stationGroupMap.get(group.getId());
//                if (stationGroups == null || stationGroups.isEmpty()) {
//                    continue;
//                }
//
//                List<Station> stations = stationGroups.stream().map(e -> stationMap.get(e.getStationId())).collect(Collectors.toList());
//                groupNumberStationMap.put(group.getMyCode(), stations);
//            }
//        }
//
//        // 排序后的每个零件
//
//        return bomIdPhaseSeqMap.values().stream().flatMap(entry -> entry.values().stream()).sorted(Comparator.comparing(ReverseDetail::getPlanStartSecond)).collect(Collectors.toList());
//
//         */
//
//        return bomIdPhaseSeqMap.values().stream().flatMap(entry -> entry.values().stream()).sorted(Comparator.comparing(ReverseDetail::getPlanStartSecond)).collect(Collectors.toList());
//    }
    public List<ReverseDetail> dayDetails(ReverseOrder reverseOrder, List<ReverseDetail> reverseDetails) {


        List<ReverseDetail> l = new ArrayList<>();
        int daySecond = projectConfig.getDaySecond();
        LocalDate endDate = reverseOrder.getDeliveryDate();

        for (ReverseDetail reverseDetail : reverseDetails) {
            int timeRemaining = reverseDetail.getProcessSecond();
            int startSecond = reverseDetail.getPlanStartSecond() % daySecond;

            List<ReverseDetail> temp = new ArrayList<>();
            for (int i = 0; timeRemaining > 0; i++) {
                int dayMi = daySecond - startSecond;
                int kkk = dayMi;

                if (timeRemaining > dayMi) {
                    timeRemaining = timeRemaining - dayMi;

                } else {
                    kkk = timeRemaining;
                    timeRemaining = 0;
                }

                ReverseDetail rd = new ReverseDetail();
                MkBeanUtils.copyPropertiesIgnore(reverseDetail, rd);

                LocalDate localDate = endDate.minusDays(i + (reverseDetail.getPlanStartSecond() / daySecond));
                rd.setReverseStartTime(LocalDateTime.of(localDate, LocalTime.of(23, 59, 59)).minusSeconds(startSecond));
                rd.setReverseEndTime(rd.getReverseStartTime().minusSeconds(kkk));
                rd.setReverseDay(localDate);
                rd.setReverseDaySecond(kkk);
                if (i == 0) {
                    startSecond = 0;
                }
                temp.add(rd);
            }

            l.addAll(temp);
        }
        return l;
    }

    public ReverseOrderCache createOrderCache(Order order, ReverseOrder rootReverseOrder, ReverseOrder reverseOrder) {

        ReverseOrderCache orderCache = new ReverseOrderCache();

        orderCache.setOrder(order);
        orderCache.setRootReverseOrder(rootReverseOrder);
        orderCache.setReverseOrder(reverseOrder);

        // 填充所有物料
        List<OrderBom> orderBomList = orderBomMapper.selectList(Wrappers.<OrderBom>lambdaQuery().eq(OrderBom::getOrderId, order.getId()));
        orderCache.setOrderBomList(orderBomList);

        // 填充所有工序
        List<OrderPhase> orderPhaseList = orderPhaseMapper.selectList(Wrappers.<OrderPhase>lambdaQuery().eq(OrderPhase::getOrderId, order.getId()));
        orderCache.setOrderPhaseList(orderPhaseList);

        return orderCache;
    }

    public ReverseFactoryCache createFactoryCache(Order order) {
        ReverseFactoryCache cache = new ReverseFactoryCache();

        // 查询所有的组
        List<Group> groupList = groupMapper.selectList(Wrappers.<Group>lambdaQuery().eq(Group::getType, 2));
        cache.setGroupList(groupList);

        // 查询所有的工作组
//        List<StationGroup> stationGroupList = stationGroupMapper.selectList(null);
//        cache.setStationGroupList(stationGroupList);

        // 查询所有工位
        List<Station> stationList = stationMapper.selectList(null);
        cache.setStationList(stationList);

        // 取出所有工位的工作能力
        List<ReverseGroup> groupRefList = stationMapper.selectAll();
        Map<String, List<ReverseGroup>> collect = groupRefList.stream().collect(Collectors.groupingBy(ReverseGroup::getGroupCode));

        cache.setWorkCenterMap(new HashMap<>());
        for (Map.Entry<String, List<ReverseGroup>> entry : collect.entrySet()) {
            List<ReverseGroup> reverseGroups = entry.getValue();
            if (reverseGroups == null || reverseGroups.isEmpty()) {
                continue;
            }

            ReverseWorkCenter center = new ReverseWorkCenter();
            center.setGroupList(reverseGroups);
            center.setStationGroupId(reverseGroups.get(0).getId());
            center.setGroupId(reverseGroups.get(0).getGroupId());
            center.setWorkAbility(reverseGroups.stream()
                    .map(ReverseGroup::getWorkAbility)
                    .max(BigDecimal::compareTo)
                    .orElse(new BigDecimal(1)));
            cache.getWorkCenterMap().put(entry.getKey(), center);
        }

        // 排除工序
//        cache.setExcludePhase(Collections.singletonList(WorkshopProp.ycPhaseCode));


        return cache;
    }


    @Transactional
    public void phaseDelete(BaseIdReqVo reqVo) {
        OrderPhase op = orderPhaseMapper.selectById(reqVo.getId());

        // 删除倒排记录
        reverseDetailMapper.deleteByPhaseId(op.getId());

        // 删除apsworkdetail
        apsWorkDetailMapper.deleteByPhaseId(op.getId());

        // 删除工序
        orderPhaseMapper.deleteRealById(op.getId());

        // 重新生成工序链
        List<OrderPhase> phaseList = orderPhaseMapper.lambdaQuery()
                .eq(OrderPhase::getBomId, op.getBomId())
                .orderByAsc(OrderPhase::getPhaseSeq)
                .list();


        OrderBom bom = orderBomMapper.selectById(op.getBomId());
        if (CollUtil.isEmpty(phaseList)) {
            bom.setWorkChain("");
        } else {
            bom.setWorkChain(phaseList.stream().map(OrderPhase::getPhaseCode).collect(Collectors.joining("-")));
        }
        orderBomMapper.updateById(bom);

    }

    @Transactional
    public void phaseUp(BaseIdReqVo reqVo) {
        OrderPhase current = orderPhaseMapper.selectById(reqVo.getId());
        List<OrderPhase> list = orderPhaseMapper.lambdaQuery()
                .lt(OrderPhase::getPhaseSeq, current.getPhaseSeq())
                .eq(OrderPhase::getBomId, current.getBomId())
                .list();

        if (CollUtil.isEmpty(list)) {
            return;
        }

        Optional<OrderPhase> max = list.stream().max(Comparator.comparing(OrderPhase::getPhaseSeq));
        if (!max.isPresent()) {
            return;
        }

        OrderPhase ltPhase = max.get();

        int temp = current.getPhaseSeq();
        current.setPhaseSeq(ltPhase.getPhaseSeq());
        ltPhase.setPhaseSeq(temp);
        orderPhaseMapper.updateById(current);
        orderPhaseMapper.updateById(ltPhase);


        // 重新生成工序链
        List<OrderPhase> phaseList = orderPhaseMapper.lambdaQuery()
                .eq(OrderPhase::getBomId, current.getBomId())
                .orderByAsc(OrderPhase::getPhaseSeq)
                .list();


        OrderBom bom = orderBomMapper.selectById(current.getBomId());
        if (CollUtil.isEmpty(phaseList)) {
            bom.setWorkChain("");
        } else {
            bom.setWorkChain(phaseList.stream().map(e -> e.getPhaseCode()).collect(Collectors.joining("-")));
        }
        orderBomMapper.updateById(bom);


    }

    @Transactional
    public void phaseDown(BaseIdReqVo reqVo) {
        OrderPhase current = orderPhaseMapper.selectById(reqVo.getId());
        List<OrderPhase> list = orderPhaseMapper.lambdaQuery()
                .gt(OrderPhase::getPhaseSeq, current.getPhaseSeq())
                .eq(OrderPhase::getBomId, current.getBomId())
                .list();

        if (CollUtil.isEmpty(list)) {
            return;
        }

        Optional<OrderPhase> max = list.stream().min(Comparator.comparing(OrderPhase::getPhaseSeq));
        if (!max.isPresent()) {
            return;
        }

        OrderPhase ltPhase = max.get();

        int temp = current.getPhaseSeq();
        current.setPhaseSeq(ltPhase.getPhaseSeq());
        ltPhase.setPhaseSeq(temp);
        orderPhaseMapper.updateById(current);
        orderPhaseMapper.updateById(ltPhase);

        // 重新生成工序链
        List<OrderPhase> phaseList = orderPhaseMapper.lambdaQuery()
                .eq(OrderPhase::getBomId, current.getBomId())
                .orderByAsc(OrderPhase::getPhaseSeq)
                .list();


        OrderBom bom = orderBomMapper.selectById(current.getBomId());
        if (CollUtil.isEmpty(phaseList)) {
            bom.setWorkChain("");
        } else {
            bom.setWorkChain(phaseList.stream().map(e -> e.getPhaseCode()).collect(Collectors.joining("-")));
        }
        orderBomMapper.updateById(bom);
    }

    @Transactional
    public Map<ApsBatch, List<Order>> reorder(OrderReorderReqVo reqVo) {

        // 找到待排产的工单详情
        List<ApsWorkDetail> todoWorkDetailList = apsWorkDetailMapper.lambdaQuery().eq(ApsWorkDetail::getStatus, 2).list();

        // 找到工单详情涉及到的订单
        List<Integer> orderIdList = todoWorkDetailList.stream().map(ApsWorkDetail::getOrderId).distinct().collect(Collectors.toList());
        List<Order> orderList = orderMapper.selectBatchIds(orderIdList);

        // 找到订单的批次
        Map<ApsBatch, List<Order>> map = new LinkedHashMap<>();

        List<Integer> batchIdList = orderList.stream().map(Order::getBatchId).distinct().collect(Collectors.toList());
        List<ApsBatch> batchList = apsBatchMapper.selectBatchIds(batchIdList);
        if (CollUtil.isEmpty(batchList)) {
            return map;
        }

        ApsBatch minBatch = batchList.stream().min(Comparator.comparing(ApsBatch::getSchedulingDateTime)).orElseThrow(() -> SyExceptionUtils.e("没有待排产的订单"));

        // 找到比这个大的所有批次
        List<ApsBatch> allBatchList = apsBatchMapper.lambdaQuery().ge(ApsBatch::getSchedulingDateTime, minBatch.getSchedulingDateTime()).list();
        List<Integer> collect = allBatchList.stream().map(BaseEntity::getId).collect(Collectors.toList());
        List<Order> allOrderList = orderMapper.lambdaQuery().in(Order::getBatchId, collect).list();
        Map<Integer, List<Order>> batchIdMap = allOrderList.stream().collect(Collectors.groupingBy(Order::getBatchId));

        for (ApsBatch apsBatch : allBatchList) {
            List<Order> orders = batchIdMap.get(apsBatch.getId());
            orders.sort(Comparator.comparing(Order::getSeq));
            map.put(apsBatch, orders);
        }

        return map;

    }

    public List<ApsOrder> apsOrders(ApsBatch apsBatch, List<Order> orders) {

//        // 验证
//        // 判断是否有排产中的订单，如果有则提示
//        LambdaQueryWrapper<Order> scheduleOrderWrapper = Wrappers.lambdaQuery();
//        scheduleOrderWrapper.eq(Order::getOrderStatus, 4);
//        scheduleOrderWrapper.eq(Order::getOrderType, 1);
//        Integer scheduleOrderCount = orderMapper.selectCount(scheduleOrderWrapper);
//
//        if(scheduleOrderCount > 0){
//            throw SyExceptionUtils.e("有排产中的订单，请稍后再试");
//        }
//        // 取出所有待排产的订单
//        LambdaQueryWrapper<Order> preScheduleOrderWrapper = Wrappers.lambdaQuery();
//        preScheduleOrderWrapper.in(Order::getOrderStatus, 3, 5);
//        preScheduleOrderWrapper.eq(Order::getOrderType, 1);
//        if(apsBatch != null){
//            preScheduleOrderWrapper.eq(Order::getBatchId, apsBatch.getId());
//        }
//        List<Order> orders = orderMapper.selectList(preScheduleOrderWrapper);
        if (CollUtil.isEmpty(orders)) {
            throw SyExceptionUtils.e("没有待排产的订单");
        }

        List<Integer> orderIds = orders.stream().map(BaseEntity::getId).collect(Collectors.toList());


        // 对apsOrders进行分组排序
        return apsOrderMapper.lambdaQuery()
                .in(ApsOrder::getOrderId, orderIds)
                .in(ApsOrder::getOrderType, 1, 3, 4)
                .list();

    }

    public List<OrderDrawingPushDetailResVo> drawingPushDetail(OrderDrawingPushDetailReqVo reqVo) {

        List<OrderDrawingPushDetailResVo> list = new ArrayList<>();

        // 查询所有零件
        LambdaQueryWrapper<OrderBom> queryWrapper1 = Wrappers.lambdaQuery();
        queryWrapper1.eq(OrderBom::getOrderId, reqVo.getOrderId());
        queryWrapper1.eq(StringUtils.hasText(reqVo.getPlmId()), OrderBom::getPlmId, reqVo.getPlmId());
        queryWrapper1.eq(OrderBom::getReadyType, 1);
        queryWrapper1.isNotNull(OrderBom::getTexture);
        List<OrderBom> orderBoms = orderBomMapper.selectList(queryWrapper1);

        // 查询该订单的图纸
        LambdaQueryWrapper<SinoCamPushDrawing> queryWrapper2 = Wrappers.lambdaQuery();
        queryWrapper2.eq(SinoCamPushDrawing::getOrderId, reqVo.getOrderId());
        if (StringUtils.hasText(reqVo.getPlmId())) {
            queryWrapper2.eq(SinoCamPushDrawing::getPartId, reqVo.getPlmId());
        }
        List<SinoCamPushDrawing> drawingList = sinoCamPushDrawingMapper.selectList(queryWrapper2);
        if (drawingList.size() == 0) {
            throw SyExceptionUtils.e("未查询到该订单的图纸推送");
        }
        Map<String, SinoCamPushDrawing> drawingMap = drawingList.stream().collect(Collectors.toMap(SinoCamPushDrawing::getPartId, Function.identity()));

        for (OrderBom orderBom : orderBoms) {
            OrderDrawingPushDetailResVo vo = new OrderDrawingPushDetailResVo();
            SinoCamPushDrawing drawing = drawingMap.get(orderBom.getPlmId());
            vo.setPlmId(orderBom.getPlmId());
            if (drawingMap.keySet().contains(orderBom.getPlmId())) {
                if (drawing.getStatus() == 4) {
                    vo.setStatus(1);
                    vo.setMessage(null);
                } else {
                    vo.setStatus(2);
                    vo.setMessage("该图纸推送失败");
                }
            } else {
                vo.setStatus(2);
                vo.setMessage("未找到该图纸的推送记录");
            }
            list.add(vo);
        }
        return list;

    }

    public List<OrderPlanPushDetailResVo> planPushDetail(OrderPlanPushDetailReqVo reqVo) {

        List<OrderPlanPushDetailResVo> list = new ArrayList<>();

        // 根据 ID 字段取包号
        List<ApsOrder> apsOrderList = apsOrderMapper.lambdaQuery().eq(ApsOrder::getOrderId, reqVo.getOrderId()).list();
        Map<Integer, ApsOrder> apsOrderSeqMap = apsOrderList.stream().collect(Collectors.toMap(ApsOrder::getSeq, Function.identity()));
        Map<Integer, ApsOrder> apsOrderIdMap = apsOrderList.stream().collect(Collectors.toMap(ApsOrder::getId, Function.identity()));

        // 查所有零件
        List<String> phaseCodeList = projectConfig.getCuttingProcess();
        LambdaQueryWrapper<ApsWorkDetail> queryWrapper1 = Wrappers.lambdaQuery();
        queryWrapper1.eq(ApsWorkDetail::getOrderId, reqVo.getOrderId());
        if (StringUtils.hasText(reqVo.getPlmId())) {
            queryWrapper1.eq(ApsWorkDetail::getMaterNo, reqVo.getPlmId());
        }
        if (reqVo.getPackageNo() != null) {
            ApsOrder apsOrderSeq = apsOrderSeqMap.get(reqVo.getPackageNo());
            queryWrapper1.eq(ApsWorkDetail::getApsOrderId, apsOrderSeq.getId());
        }
        queryWrapper1.eq(ApsWorkDetail::getStatus, 2);
        queryWrapper1.in(ApsWorkDetail::getPhaseCode, phaseCodeList);
        List<ApsWorkDetail> apsWorkDetailList = apsWorkDetailMapper.selectList(queryWrapper1);

        // 查所有推送的计划
        LambdaQueryWrapper<SinoCamPushPlan> queryWrapper2 = Wrappers.lambdaQuery();
        queryWrapper2.eq(SinoCamPushPlan::getOrderId, reqVo.getOrderId());
        if (StringUtils.hasText(reqVo.getPlmId())) {
            queryWrapper2.eq(SinoCamPushPlan::getPartId, reqVo.getPlmId());
        }
        List<SinoCamPushPlan> pushPlanList = sinoCamPushPlanMapper.selectList(queryWrapper2);
        if (pushPlanList.size() == 0) {
            throw SyExceptionUtils.e("未查询到该订单的计划推送");
        }
        Map<String, SinoCamPushPlan> pushPlanMap = pushPlanList.stream().collect(Collectors.toMap(SinoCamPushPlan::getNestPlanId, Function.identity()));

        for (ApsWorkDetail apsWorkDetail : apsWorkDetailList) {
            OrderPlanPushDetailResVo vo = new OrderPlanPushDetailResVo();
            ApsOrder apsOrder = apsOrderIdMap.get(apsWorkDetail.getApsOrderId());
            vo.setPlmId(apsWorkDetail.getMaterNo());
            vo.setPackageNo(apsOrder.getSeq());
            if (!pushPlanMap.keySet().contains(apsWorkDetail.getId().toString())) {
                vo.setStatus(1);
                vo.setQuantity("No Push Plan");
                list.add(vo);
                continue;
            }
            SinoCamPushPlan plan = pushPlanMap.get(apsWorkDetail.getId().toString());
            if (plan.getStatus() == 5) {
                vo.setStatus(1);
                vo.setQuantity("push failure");
            } else if (plan.getStatus() == 4) {
                if (!Objects.equals(apsWorkDetail.getTotalCount(), plan.getPlanAmount())) {
                    vo.setStatus(2);
                    vo.setQuantity(plan.getPlanAmount() + "/" + apsWorkDetail.getTotalCount());
                } else {
                    vo.setStatus(3);
                    vo.setQuantity(plan.getPlanAmount() + "/" + apsWorkDetail.getTotalCount());
                }
            } else {
                vo.setStatus(3);
                vo.setQuantity("Consuming");
            }
            list.add(vo);
        }

        return list;
    }

    public List<OrderReceiveDetailResVo> receiveDetail(OrderReceiveDetailReqVo reqVo) {

        List<OrderReceiveDetailResVo> list = new ArrayList<>();

        // 根据 ID 字段取包号
        List<ApsOrder> apsOrderList = apsOrderMapper.lambdaQuery().eq(ApsOrder::getOrderId, reqVo.getOrderId()).list();
        Map<Integer, ApsOrder> apsOrderSeqMap = apsOrderList.stream().collect(Collectors.toMap(ApsOrder::getSeq, Function.identity()));
        Map<Integer, ApsOrder> apsOrderIdMap = apsOrderList.stream().collect(Collectors.toMap(ApsOrder::getId, Function.identity()));

        // 查所有零件
        List<String> phaseCodeList = projectConfig.getCuttingProcess();
        LambdaQueryWrapper<ApsWorkDetail> queryWrapper1 = Wrappers.lambdaQuery();
        queryWrapper1.eq(ApsWorkDetail::getOrderId, reqVo.getOrderId());
        if (StringUtils.hasText(reqVo.getPlmId())) {
            queryWrapper1.eq(ApsWorkDetail::getMaterNo, reqVo.getPlmId());
        }
        if (reqVo.getPackageNo() != null) {
            ApsOrder apsOrderSeq = apsOrderSeqMap.get(reqVo.getPackageNo());
            queryWrapper1.eq(ApsWorkDetail::getApsOrderId, apsOrderSeq.getId());
        }
        queryWrapper1.eq(ApsWorkDetail::getStatus, 2);
        queryWrapper1.in(ApsWorkDetail::getPhaseCode, phaseCodeList);
        List<ApsWorkDetail> apsWorkDetailList = apsWorkDetailMapper.selectList(queryWrapper1);

        // 查所有接收到的零件计划
        LambdaQueryWrapper<SinoCamReceiveNestPart> queryWrapper2 = Wrappers.lambdaQuery();
        String code = reqVo.getOrderId().toString() + "#";
        queryWrapper2.like(SinoCamReceiveNestPart::getUniCode, code);
        if (StringUtils.hasText(reqVo.getPlmId())) {
            queryWrapper2.eq(SinoCamReceiveNestPart::getPartId, reqVo.getPlmId());
        }
        List<SinoCamReceiveNestPart> nestPartList = sinoCamReceiveNestPartMapper.selectList(queryWrapper2);
        if (nestPartList.size() == 0) {
            throw SyExceptionUtils.e("未查询到该订单的接收计划");
        }
        Map<String, SinoCamReceiveNestPart> nestPartMap = nestPartList.stream().collect(Collectors.toMap(SinoCamReceiveNestPart::getNestPlanId, Function.identity()));

        for (ApsWorkDetail apsWorkDetail : apsWorkDetailList) {
            OrderReceiveDetailResVo vo = new OrderReceiveDetailResVo();
            ApsOrder apsOrder = apsOrderIdMap.get(apsWorkDetail.getApsOrderId());
            vo.setPlmId(apsWorkDetail.getMaterNo());
            vo.setPackageNo(apsOrder.getSeq());
            if (!nestPartMap.keySet().contains(apsWorkDetail.getId().toString())) {
                vo.setStatus(1);
                vo.setQuantity("No Receive Part Plan");
                list.add(vo);
                continue;
            }
            SinoCamReceiveNestPart part = nestPartMap.get(apsWorkDetail.getId().toString());
            BigDecimal quantity = new BigDecimal(part.getQuantity());
            int result = quantity.compareTo(apsWorkDetail.getTotalCount());
            if (result < 0) {
                vo.setStatus(2);
                vo.setQuantity(part.getQuantity() + "/" + apsWorkDetail.getTotalCount());
            } else {
                vo.setStatus(3);
                vo.setQuantity(part.getQuantity() + "/" + apsWorkDetail.getTotalCount());
            }
            list.add(vo);
        }

        return list;
    }

    public BasePageResVo<OrderPushStatusResVo> pushStatus(OrderPushStatusReqVo reqVo) {

        // 使用卓畅套料库表
        QueryWrapper<SinoCamPushDrawing> qw = Wrappers.query();
        qw.eq("d.order_id", reqVo.getOrderId());
        if (StringUtils.hasText(reqVo.getPackageCode())) {
            qw.like("p.processing_no", reqVo.getPackageCode());
        }
        if (StringUtils.hasText(reqVo.getAssPartName())) {
            qw.like("p.component_name", reqVo.getAssPartName());
        }
        if (StringUtils.hasText(reqVo.getAssPartCode())) {
            qw.like("p.component_id", reqVo.getAssPartCode());
        }
        if (StringUtils.hasText(reqVo.getPartCode())) {
            qw.like("d.part_id", reqVo.getPartCode());
        }
        if (StringUtils.hasText(reqVo.getPartName())) {
            qw.like("d.part_name", reqVo.getPartName());
        }
        if (StringUtils.hasText(reqVo.getTexture())) {
            qw.like("d.texture", reqVo.getTexture());
        }
        if (reqVo.getThickness() != null) {
            qw.eq("d.thick_ness", reqVo.getThickness());
        }
        if (reqVo.getStatus() != null) {
            if (reqVo.getStatus() == 2) {
                qw.eq("d.status", reqVo.getStatus());
            } else if (reqVo.getStatus() == 4 || reqVo.getStatus() == 5) {
                qw.eq("p.status", reqVo.getStatus());
            } else if (reqVo.getStatus() == 1 || reqVo.getStatus() == 3) {
                qw.eq("p.status", reqVo.getStatus()); // 后续做调整修改，所有零件默认都是新增待推送，然后选择进行推送。
            }
        }
        Page<OrderPushStatusResVo> orderPushStatusResVoPage = sinoCamPushDrawingMapper.pushStatusSelect(reqVo.toPage(), qw);

        List<SinoCamPushDrawing> drawList = sinoCamPushDrawingMapper.lambdaQuery()
                .eq(SinoCamPushDrawing::getOrderId, reqVo.getOrderId())
                .eq(SinoCamPushDrawing::getStatus, 2)
                .eq(SinoCamPushDrawing::getDrawStatus, 2)
                .list();
        if (!drawList.isEmpty()) {
            Map<String, SinoCamPushDrawing> drawMap = drawList.stream().collect(Collectors.toMap(SinoCamPushDrawing::getPartId, Function.identity()));
            for (OrderPushStatusResVo vo : orderPushStatusResVoPage.getRecords()) {
                if (drawMap.containsKey(vo.getPartCode())) {
                    SinoCamPushDrawing d = drawMap.get(vo.getPartCode());
                    vo.setStatus(d.getStatus());
                    vo.setRemark(d.getErrorMsg());
                }
                vo.setThickness(vo.getThickness().setScale(0, RoundingMode.HALF_UP));
            }
        }

        return BasePageResVo.of(orderPushStatusResVoPage, OrderPushStatusResVo.class);
    }

    public BasePageResVo<OrderDrawPushStatusResVo> drawPushStatus(OrderDrawPushStatusReqVo reqVo) {
        QueryWrapper<SinoCamPushDrawing> qw = Wrappers.query();
        qw.ne("o.order_type", 2);
        qw.eq("o.id", reqVo.getOrderId());
        if (StringUtils.hasText(reqVo.getUniCode())) {
            qw.like("d.uni_mater_code", reqVo.getUniCode());
        }
        if (StringUtils.hasText(reqVo.getPartCode())) {
            qw.like("d.part_id", reqVo.getPartCode());
        }
        if (StringUtils.hasText(reqVo.getPartName())) {
            qw.like("d.part_name", reqVo.getPartName());
        }
        if (StringUtils.hasText(reqVo.getTexture())) {
            qw.like("d.texture", reqVo.getTexture());
        }
        if (reqVo.getThickness() != null) {
            qw.eq("d.thick_ness", reqVo.getThickness());
        }
        if (reqVo.getPushStatus() != null) {
            qw.eq("d.status", reqVo.getPushStatus());
        }
        Page<OrderDrawPushStatusResVo> page = sinoCamPushDrawingMapper.drawPushStatus(reqVo.toPage(), qw);
        return BasePageResVo.of(page, OrderDrawPushStatusResVo.class);
    }

    public BasePageResVo<OrderPlanPushStatusResVo> planPushStatus(OrderPlanPushStatusReqVo reqVo) {
        QueryWrapper<SinoCamPushPlan> qw = Wrappers.query();
        qw.ne("o.order_type", 2);
        if (StringUtils.hasText(reqVo.getPackageCode())) {
            qw.like("p.processing_no", reqVo.getPackageCode());
        }
        if (StringUtils.hasText(reqVo.getAssPartName())) {
            qw.like("p.component_name", reqVo.getAssPartName());
        }
        if (StringUtils.hasText(reqVo.getUniCode())) {
            qw.eq("p.uni_mater_code", reqVo.getUniCode());
        }
        if (StringUtils.hasText(reqVo.getPartCode())) {
            qw.like("p.part_id", reqVo.getPartCode());
        }
        if (StringUtils.hasText(reqVo.getPartName())) {
            qw.like("p.part_name", reqVo.getPartName());
        }
        if (reqVo.getPushStatus() != null) {
            qw.eq("p.status", reqVo.getPushStatus());
        }
        Page<OrderPlanPushStatusResVo> page = sinoCamPushPlanMapper.planPushStatus(reqVo.toPage(), qw);
        return BasePageResVo.of(page, OrderPlanPushStatusResVo.class);
    }

    @Transactional
    public void addOrder(OrderAddReqVo reqVo) {
        Order order = new Order();
        order.setOrderCode(reqVo.getOrderConstructNo());
        order.setConstructNo(reqVo.getOrderConstructNo());
        order.setPlmId(reqVo.getOrderConstructNo());
        order.setMaterCode(reqVo.getOrderConstructNo());

        if (reqVo.getOrderQty() == null) {
            order.setOrderQty(1);
        } else {
            order.setOrderQty(reqVo.getOrderQty());
        }
        order.setFinishQty(0);
        order.setOrderType(reqVo.getOrderOrderType()); // 3是外揽件
        if (order.getOrderType().equals(3)) {
            order.setOrderStatus(1);
            order.setMaterName("外揽件");
        } else if (order.getOrderType().equals(4)) {
            order.setOrderStatus(1);
            order.setMaterName("工装件");
        } else {
            order.setOrderStatus(1);
        }
        order.setFactoryCode("170");
        order.setOrderDateTime(LocalDateTime.now());
        order.setDeliveryDateTime(reqVo.getOrderDeliveryDateTime());

        List<Order> list = orderMapper.lambdaQuery().eq(Order::getConstructNo, order.getConstructNo()).list();

        if (CollUtil.isNotEmpty(list)) {
            if (list.get(0).getSerialNum() == null) {
                Order max = orderMapper.lambdaQuery().orderByDesc(Order::getSerialNum).last(" limit 1").one();
                int serialCode = 0;
                if (max != null && max.getSerialNum() != null) {
                    serialCode = max.getSerialNum();
                }
                order.setSerialNum(serialCode + 1);
                order.setSerialCode(String.format("%04d-", order.getSerialNum()) + order.getConstructNo());
            } else {
                order.setSerialNum(list.get(0).getSerialNum());
                order.setSerialCode(list.get(0).getSerialCode());
            }
        } else {
            Order max = orderMapper.lambdaQuery().orderByDesc(Order::getSerialNum).last(" limit 1").one();
            int serialCode = 0;
            if (max != null && max.getSerialNum() != null) {
                serialCode = max.getSerialNum();
            }
            order.setSerialNum(serialCode + 1);
            order.setSerialCode(String.format("%04d-", order.getSerialNum()) + order.getConstructNo());
        }

        orderMapper.insert(order);


        OrderBom orderBom = new OrderBom();
        orderBom.setMaterName(order.getMaterName());
        orderBom.setMaterCode(order.getMaterCode());
        orderBom.setPlmId(order.getPlmId());
//        orderBom.setTexture(reqVo.getTexture());
//        orderBom.setMaterHigh(reqVo.getMaterHigh());
//        orderBom.setStandards(reqVo.getStandards());
//        orderBom.setDrawingPath(reqVo.getDrawingPath());
//        orderBom.setDrawing(reqVo.getDrawing());

        if (order.getOrderType().equals(3)) {
            orderBom.setReadyType(3);
        } else {
            orderBom.setReadyType(1);
        }
        orderBom.setPartCount(new BigDecimal(1));
        orderBom.setWorkChain("WW");
        orderBom.setWorkOrderCode(WorkshopProp.APPEND_BOM_CODE);
        orderBom.setErpCode(WorkshopProp.APPEND_BOM_CODE);// 添加

        orderBom.setTopFlag(0);
        orderBom.setModifyStatus(LocalDateTime.now().format(DatePattern.PURE_DATETIME_FORMATTER));
        orderBom.setOrderId(order.getId());
        orderBom.setFactoryNo("170");
        orderBom.setLevel(1);
        orderBom.setTotalCount(new BigDecimal(1));
        orderBom.setAssemblyPath("/" + orderBom.getMaterCode());
        orderBom.setMaterType("Assembly");

        orderBomMapper.insert(orderBom);

        OrderPhase orderPhase = new OrderPhase();
        orderPhase.setOrderId(orderBom.getOrderId());
        orderPhase.setBomId(orderBom.getId());
        orderPhase.setWorkChain(orderBom.getWorkChain());
        orderPhase.setPhaseName("委外");
        orderPhase.setPhaseCode("WW");
        orderPhase.setMaterNo(orderBom.getMaterCode());
        orderPhase.setMaterName(orderBom.getMaterName());
        orderPhase.setWorkGroupNumber("WW");
        orderPhase.setPhaseSeq(1);
        orderPhase.setWorkTime(1);
        orderPhase.setOriWorkTime(orderPhase.getWorkTime());
        orderPhaseMapper.insert(orderPhase);

    }

    @SneakyThrows
    public Workbook syncError(OrderSyncErrorReqVo reqVo) {
        String s = stringRedisTemplate.opsForValue().get("mom-srv-aps:order-sync:error:" + reqVo.getConstructNo() + ":" + reqVo.getMaterCode());
        if (s == null) {
            s = stringRedisTemplate.opsForValue().get("mom-srv-aps:order-sync:error:" + reqVo.getMaterCode() + ":" + reqVo.getMaterCode());
        }
        List<OrderExternalSyncErrorResVo> errorList = jacksonObjectMapper.readValue(s, new TypeReference<ArrayList<OrderExternalSyncErrorResVo>>() {
        });

        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("同步错误");

        Map<Integer, String> params = new HashMap<>();
        params.put(1, "订单异常");
        params.put(2, "BOM");
        params.put(3, "零件");
        params.put(4, "工序");

        List<String> title = new ArrayList<>();
        title.add("错误类型");
        title.add("施工号");
        title.add("工单号");
        title.add("物料号");
        title.add("名称");
        title.add("PLMID");
        title.add("规格");
        title.add("单位数量");
        title.add("父级物料号");
        title.add("物料状态");
        title.add("图号");
        title.add("验证结果");


        sheet.setColumnWidth(11, 256 * 60);
        PoiUtils.title(sheet, title);
//        for (int i = 0; i < title.size(); i++) {
//            Cell timeCell = row.createCell(i);
//            timeCell.setCellValue(title.get(i));
//
//        }

        for (int i = 0; i < errorList.size(); i++) {
            Row dataRow = sheet.createRow(i + 1);
//            Cell typeCell = dataRow.createCell(0);
//            Cell contentCell = dataRow.createCell(1);
//            typeCell.setCellValue(errorList.get(i).getErrorType());
//            contentCell.setCellValue(errorList.get(i).getErrorMessage());


            PoiUtils.cells(dataRow,
                    params.get(errorList.get(i).getErrorType()),
                    errorList.get(i).getConstructNo(),
                    errorList.get(i).getWorkOrderCode(),
                    errorList.get(i).getMaterCode(),
                    errorList.get(i).getMaterialName(),
                    errorList.get(i).getPlmId(),
                    errorList.get(i).getStandards(),
                    errorList.get(i).getPartCount(),
                    errorList.get(i).getPmCode(),
                    errorList.get(i).getMaterialState(),
                    errorList.get(i).getPaintCode(),
                    errorList.get(i).getErrorMessage()
            );
        }


        return workbook;
    }

    @Transactional
    public void phaseEdit(OrderPhaseEditReqVo reqVo) {

        OrderPhase oldPhase = orderPhaseMapper.selectById(reqVo.getId());

        if (reqVo.getWorkTime() == null) {
            throw SyExceptionUtils.e("工时不能为空");
        }
        if (!StringUtils.hasText(reqVo.getGroupCode())) {
            throw SyExceptionUtils.e("工作组不能为空");
        }

        OrderPhase orderPhase = new OrderPhase();
        orderPhase.setId(reqVo.getId());
        orderPhase.setWorkGroupNumber(reqVo.getGroupCode());
        orderPhase.setWorkTime(reqVo.getWorkTime().multiply(new BigDecimal(60)).setScale(0, RoundingMode.HALF_UP).intValue());
        orderPhaseMapper.updateById(orderPhase);

        orderPhase = orderPhaseMapper.selectById(reqVo.getId());

        Order order = orderMapper.selectById(oldPhase.getOrderId());

        if (order.getOrderStatus() >= 3) {
            throw SyExceptionUtils.e("该订单已进入排产，禁止修改工序");
        }

//        OrderPhase orderPhase = MkBeanUtils.copyProperties(reqVo, OrderPhase.class);
//        Phase phase = phaseMapper.selectById(reqVo.getPhaseId());
        OrderBom bom = orderBomMapper.selectById(orderPhase.getBomId());
        Group group = groupMapper.lambdaQuery().eq(Group::getMyCode, orderPhase.getWorkGroupNumber()).one();
//        List<OrderPhase> phaseList = orderPhaseMapper.lambdaQuery()
//                .eq(OrderPhase::getBomId, bom.getId())
//                .orderByAsc(OrderPhase::getPhaseSeq)
//                .list();
//
//        int index = 0;
//        List<String> workChaineList = new ArrayList<>();
//        if (CollUtil.isNotEmpty(phaseList)) {
//            index = phaseList.get(phaseList.size() - 1).getPhaseSeq();
//            workChaineList.addAll(phaseList.stream().map(OrderPhase::getPhaseCode).collect(Collectors.toList()));
//        }
//        workChaineList.add(phase.getMyCode());
//        String workChain = String.join("-", workChaineList);
//        bom.setWorkChain(workChain);
//        orderBomMapper.updateById(bom);
//
//        index++;
//        orderPhase.setOrderId(bom.getOrderId());
//        orderPhase.setBomId(bom.getId());
//        orderPhase.setWorkChain(bom.getWorkChain());
//        orderPhase.setPhaseName(phase.getName());
//        orderPhase.setPhaseCode(phase.getMyCode());
//        orderPhase.setMaterNo(bom.getMaterCode());
//        orderPhase.setMaterName(bom.getMaterName());
//        orderPhase.setWorkGroupNumber(group.getMyCode());
//        orderPhase.setPhaseSeq(index);
//        orderPhaseMapper.insert(orderPhase);

//        for (OrderPhase orderPhase1 : phaseList) {
//            orderPhase1.setWorkChain(workChain);
//            orderPhaseMapper.updateById(orderPhase1);
//        }
//        phaseList.add(orderPhase);
        List<OrderPhase> phaseList = orderPhaseMapper.lambdaQuery().eq(OrderPhase::getBomId, bom.getId()).orderByAsc(OrderPhase::getPhaseSeq).list();
        /*if (bom.getReadyType() == 3) { // 外来件
            outScheduleAddPhase(order, bom, phaseList, orderPhase);
            return;
        }*/

        if (order.getOrderStatus() >= 9) {
            throw SyExceptionUtils.e("订单完成，禁止添加工序");
        }

        if (order.getOrderStatus() <= 0) {
            throw SyExceptionUtils.e("订单未同步，禁止添加工序");
        }

        if (order.getOrderStatus() == 1) {
            return;
        }

        if (order.getOrderStatus() == 4) {
            throw SyExceptionUtils.e("有订单正在排产，请稍后再操作");
        }

        // 处理倒排工序
        ReverseOrder root = reverseOrderMapper.lambdaQuery()
                .eq(ReverseOrder::getOrderId, order.getId())
                .isNull(ReverseOrder::getParentId)
                .one();
        if (root == null) {
            throw SyExceptionUtils.e("订单异常");
        }

        Integer count = orderPhaseMapper.lambdaQuery()
                .eq(OrderPhase::getOrderId, order.getId())
                .isNull(OrderPhase::getWorkTime)
                .isNull(OrderPhase::getWorkGroupNumber)
                .count();

        if (count > 0) {
            return;
        }

        List<ReverseOrder> children = reverseOrderMapper.lambdaQuery()
                .eq(ReverseOrder::getOrderId, order.getId())
                .in(ReverseOrder::getParentId, root.getId())
                .orderByAsc(ReverseOrder::getSplitNum)
                .list();

        reverseDetailMapper.deleteHard(order.getId());


        // 倒序排产
        reverseOrderService.reverseAllScheduling(order, root, children, new HashMap<>());

        root.setPlanStartDateTime(children.stream().min(Comparator.comparing(ReverseOrder::getPlanStartDateTime)).orElseGet(ReverseOrder::new).getPlanStartDateTime());
        root.setPlanEndDateTime(children.stream().max(Comparator.comparing(ReverseOrder::getPlanEndDateTime)).orElseGet(ReverseOrder::new).getPlanEndDateTime());
        reverseOrderMapper.updateById(root);

//        1。有没有走到倒排  有，添加倒排记录
//        2。有没有走到待排产，如果并且状态是待发布 未排产

        if (order.getOrderStatus().equals(3) || order.getOrderStatus().equals(5)) {
            LambdaUpdateWrapper<ApsOrder> wr = Wrappers.lambdaUpdate();
            wr.set(ApsOrder::getOrderStatus, 3);
            wr.set(ApsOrder::getPlanStartDateTime, null);
            wr.set(ApsOrder::getPlanEndDateTime, null);
            wr.in(ApsOrder::getOrderId, order.getId());
            apsOrderMapper.update(null, wr);
            apsWorkOrderMapper.deleteOrderId(order.getId());
            apsWorkDetailMapper.deleteOrderId(order.getId());
            apsDetailWeekdayMapper.deleteOrderId(order.getId());

            order.setOrderStatus(3);
            orderMapper.updateById(order);
            return;
        }

        List<ApsOrder> apsOrderList = apsOrderMapper.lambdaQuery().eq(ApsOrder::getOrderId, order.getId()).list();
        Map<Integer, ApsOrder> apsOrderMap = apsOrderList.stream().collect(Collectors.toMap(e -> e.getId(), Function.identity()));

        // 3。已发布，造排产计划的数据
        if (order.getOrderStatus() < 6) {
            return;
        }

        List<OrderBom> apsWorkOrderList = apsWorkOrderMapper.notInBom(order.getId());

        List<Integer> parentList = apsWorkOrderList.stream().filter(e -> e.getWorkChain().equals("WL")).map(OrderBom::getPid).filter(Objects::nonNull).distinct().collect(Collectors.toList());

        if (CollUtil.isEmpty(parentList)) {
            return;
        }
        List<OrderBom> orderBomList = orderBomMapper.selectBatchIds(parentList);
        if (CollUtil.isEmpty(orderBomList)) {
            return;
        }
        Map<Integer, OrderBom> orderBomMap = orderBomList.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        List<OrderBom> collect = apsWorkOrderList.stream()
                .filter(e -> {
                    return orderBomMap.get(e.getPid()) != null && orderBomMap.get(e.getPid()).getWorkChain().equals("WL");
                })
                .collect(Collectors.toList());

        Map<Integer, OrderBom> workOrderMap = collect.stream().collect(Collectors.toMap(e -> e.getId(), e -> e));


        apsWorkOrderList.removeIf(e -> workOrderMap.get(e.getId()) != null);

        List<ApsWorkOrder> apsWorkOrderEntity = apsWorkOrderList.stream()
//                .filter(e-> !e.getMaterCode().startsWith("0"))// 跳过原材料
                .map(e -> {
                    ApsWorkOrder workOrder = MkBeanUtils.copyProperties(e, ApsWorkOrder.class);
                    workOrder.setOrderId(e.getOrderId());
                    workOrder.setBomId(e.getId());
                    workOrder.setBomPid(e.getPid());
                    workOrder.setId(null);
                    workOrder.setPid(null);
                    workOrder.setStatus(2);
                    workOrder.setFinishCount(new BigDecimal(0));
                    workOrder.setTotalCount(e.getTotalCount());
                    workOrder.setOrderType(order.getOrderType());
                    workOrder.setPlmId(e.getPlmId());
                    return workOrder;
                })
                .sorted(Comparator.comparing(ApsWorkOrder::getLevel))
                .flatMap(e -> {
                    List<ApsWorkOrder> parentAwo = apsWorkOrderMapper.lambdaQuery()
                            .eq(ApsWorkOrder::getOrderId, order.getId())
                            .eq(ApsWorkOrder::getBomId, e.getBomPid())
                            .list();

                    return parentAwo.stream().map(e1 -> {
                        ApsWorkOrder apsWorkOrder = MkBeanUtils.copyProperties(e, ApsWorkOrder.class);
                        apsWorkOrder.setPid(e1.getId());
                        apsWorkOrder.setApsOrderId(e1.getApsOrderId());
                        apsWorkOrder.setOrderCount(bom.getTotalCount().multiply(new BigDecimal(apsOrderMap.get(apsWorkOrder.getApsOrderId()).getOrderQty())));

                        apsWorkOrder.setPlanStartDateTime(e1.getPlanStartDateTime());
                        apsWorkOrder.setPlanEndDateTime(e1.getPlanStartDateTime());
                        apsWorkOrder.setAppendFlag(2);
                        return apsWorkOrder;
                    });


                })
                .collect(Collectors.toList());


        apsWorkOrderMapper.insertBatch(apsWorkOrderEntity);

        // 找到每个BOM的工序链，开始添加工序
        List<Integer> addBomIdList = apsWorkOrderEntity.stream().map(ApsWorkOrder::getBomId).distinct().collect(Collectors.toList());
        List<OrderPhase> addPhaseList = orderPhaseMapper.lambdaQuery().in(OrderPhase::getBomId, addBomIdList).list();
        Map<Integer, List<OrderPhase>> phaseMap = addPhaseList.stream().collect(Collectors.groupingBy(OrderPhase::getBomId));
//        phaseList.sort(Comparator.comparing(OrderPhase::getPhaseSeq));
//
//        List<ReverseDetail> reverseDetails = reverseDetailMapper.lambdaQuery().eq(ReverseDetail::getBomId, bom.getId()).list();
//        Map<Integer, Map<Integer, List<ReverseDetail>>> collect1 = reverseDetails.stream().collect(Collectors.groupingBy(ReverseDetail::getReverseOrderId, Collectors.groupingBy(ReverseDetail::getPhaseId)));
//
        List<ApsWorkDetail> apsWorkDetails = new ArrayList<>();
        for (ApsWorkOrder workOrder : apsWorkOrderEntity) {

            List<OrderPhase> phaseList1 = phaseMap.get(workOrder.getBomId());
            phaseList1.sort(Comparator.comparing(OrderPhase::getPhaseSeq).reversed());

            ApsOrder apsOrder = apsOrderMapper.selectById(workOrder.getApsOrderId());

            for (OrderPhase phase : phaseList1) {
                ApsWorkDetail apsWorkDetail = new ApsWorkDetail();
                apsWorkDetail.setOrderId(order.getId());
                apsWorkDetail.setApsOrderId(workOrder.getApsOrderId());
                apsWorkDetail.setApsWorkOrderId(workOrder.getId());
                apsWorkDetail.setApsWorkOrderPid(workOrder.getPid());


                if (projectConfig.getIgnorePhaseCodeList().contains(phase.getPhaseCode())) {
                    continue;
                }

                apsWorkDetail.setPhaseId(phase.getId());
                apsWorkDetail.setWorkTime(phase.getWorkTime());

                apsWorkDetail.setPhaseSeq(phase.getPhaseSeq());
                apsWorkDetail.setPhaseCode(phase.getPhaseCode());
                apsWorkDetail.setPhaseName(phase.getPhaseName());
                apsWorkDetail.setPhaseCode(phase.getPhaseCode());
                apsWorkDetail.setMaterNo(phase.getMaterNo());
                apsWorkDetail.setMaterName(phase.getMaterName());
                apsWorkDetail.setGroupCode(phase.getWorkGroupNumber());
                apsWorkDetail.setOrderType(order.getOrderType());

                // 从倒排表里取
                apsWorkDetail.setPartCount(bom.getPartCount());
                apsWorkDetail.setTotalCount(workOrder.getOrderCount());
                apsWorkDetail.setGroupId(group.getId());
                apsWorkDetail.setProcessCount(new BigDecimal(0));
                apsWorkDetail.setFinishCount(new BigDecimal(0));
                apsWorkDetail.setStatus(1);


                apsWorkDetail.setDetailSeq(null);
                apsWorkDetail.setApsOrderId(workOrder.getApsOrderId());

                apsWorkDetail.setTotalWorkTime(apsWorkDetail.getTotalCount().multiply(new BigDecimal(phase.getWorkTime())).intValue());

                ReverseDetail one = reverseDetailMapper.lambdaQuery()
                        .eq(ReverseDetail::getReverseOrderId, apsOrder.getReverseId())
                        .eq(ReverseDetail::getPhaseId, apsWorkDetail.getPhaseId())
                        .one();
                if (one == null) {
                    continue;
                }

                apsWorkDetail.setReverseDetailId(one.getId());
                apsWorkDetail.setAppendFlag(2);
                apsWorkDetail.setPlanEndDateTime(workOrder.getPlanStartDateTime());
                apsWorkDetail.setPlanStartDateTime(apsWorkDetail.getPlanEndDateTime().minusSeconds(apsWorkDetail.getTotalWorkTime()));
                apsWorkDetails.add(apsWorkDetail);

                workOrder.setPlanStartDateTime(apsWorkDetail.getPlanStartDateTime());
            }


            apsWorkOrderMapper.updateById(workOrder);
        }

        List<String> groupCodeList = addPhaseList.stream().map(OrderPhase::getWorkGroupNumber).distinct().collect(Collectors.toList());
        List<Group> groupList = groupMapper.lambdaQuery().in(Group::getMyCode, groupCodeList).list();
        Map<Integer, Group> groupMap = groupList.stream().collect(Collectors.toMap(e -> e.getId(), Function.identity()));

        List<Station> stationListTemp = stationMapper.lambdaQuery().in(Station::getGroupId, groupList.stream().map(e -> e.getId()).distinct().collect(Collectors.toList())).list();
        Map<Integer, Station> stationMap = stationListTemp.stream().collect(Collectors.toMap(e -> e.getId(), Function.identity()));

        Map<String, List<Station>> map = new HashMap<>();
        for (Station station : stationListTemp) {
            Group g = groupMap.get(station.getGroupId());
            if (g == null) {
                continue;
            }
            List<Station> stationList = map.computeIfAbsent(g.getMyCode(), k -> new ArrayList<>());
            stationList.add(station);
        }


        List<ApsWorkDetail> collect12 = apsWorkDetails.stream()
                .flatMap(e -> {

                    List<Station> stationList = map.get(e.getGroupCode());
                    int smallTransfer = stationList.get(0).getSmallTransfer() == null ? 0 : stationList.get(0).getSmallTransfer();

                    if (CollUtil.isEmpty(stationList)) {
                        throw SyExceptionUtils.e("{}没有工位", e.getGroupCode());
                    }
                    e.setStationId(stationList.get(0).getId());

                    if (smallTransfer <= 0) {
                        return Stream.of(e);
                    }

                    int div = e.getTotalCount().divide(new BigDecimal(smallTransfer), 0, RoundingMode.DOWN).intValue();

                    BigDecimal subtract = e.getTotalCount().subtract(new BigDecimal(smallTransfer).multiply(new BigDecimal(div)));


                    List<ApsWorkDetail> l = new ArrayList<>();

                    for (int i = 0; i < div; i++) {
                        ApsWorkDetail apsWorkDetail = MkBeanUtils.copyProperties(e, ApsWorkDetail.class);
                        apsWorkDetail.setTotalCount(new BigDecimal(smallTransfer));
                        apsWorkDetail.setStationId(stationList.get(0).getId());
                        l.add(apsWorkDetail);
                    }

                    if (subtract.compareTo(BigDecimal.ZERO) > 0) {
                        ApsWorkDetail apsWorkDetail = MkBeanUtils.copyProperties(e, ApsWorkDetail.class);
                        apsWorkDetail.setTotalCount(subtract);
                        apsWorkDetail.setStationId(stationList.get(0).getId());
                        l.add(apsWorkDetail);
                    }

                    return l.stream();

                })
                .collect(Collectors.toList());


        for (ApsWorkDetail apsWorkDetail : collect12) {
            apsWorkDetail.setType(2);
            apsWorkDetail.setStatus(2);
            apsWorkDetailMapper.insert(apsWorkDetail);
        }

//        4、有没有推送过套料，如果有的话，推送到套料软件

        // 如果是激割或者火割，则推送套料
        if (order.getPushStatus() < 2) {
            return;
        }

        List<String> splitPhaseList = Arrays.asList("JG", "HG");
        if (order.getOrderStatus() >= 6) {

            Map<Integer, ApsWorkOrder> workOrderMap1 = apsWorkOrderEntity.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

            List<ApsWorkDetail> splitDetailList = collect12.stream().filter(e -> splitPhaseList.contains(e.getPhaseCode())).collect(Collectors.toList());
            for (ApsWorkDetail apsWorkDetail : splitDetailList) {

                ApsWorkOrder apsWorkOrder = workOrderMap1.get(apsWorkDetail.getApsWorkOrderId());

                List<ImportMbdDxf> importMbdDxfList = importMbdDxfMapper.lambdaQuery().in(ImportMbdDxf::getPlmid, bom.getPlmId()).list();
                Map<String, ImportMbdDxf> mbdDxfMap = importMbdDxfList.stream().collect(Collectors.toMap(ImportMbdDxf::getPlmid, Function.identity(), (a, b) -> b));

                List<PlateStandard> plateStandardList = plateStandardMapper.lambdaQuery().in(PlateStandard::getNorm, apsWorkOrder.getStandards()).list();
                Map<String, List<PlateStandard>> plateStandardMap = plateStandardList.stream().collect(Collectors.groupingBy(PlateStandard::getNorm));

                OrderBom orderBom = orderBomMapper.selectById(apsWorkOrder.getBomId());

                hexagonNestOldUtils.saveDraw(apsWorkOrder, order, orderBom, mbdDxfMap);

                ApsWorkOrder pa = apsWorkOrderMapper.selectById(apsWorkOrder.getPid());
                ApsOrder apsOrder = apsOrderMapper.selectById(pa.getApsOrderId());
                hexagonNestOldUtils.savePlan(apsWorkDetail, order, apsOrder, apsWorkOrder, pa, plateStandardMap, mbdDxfMap);

            }
            order.setPushStatus(4);
            orderMapper.updateById(order);
        }

//            List<OrderBom> bomList = sourceBomList.stream().filter(e -> !(e.getPlmId().startsWith("010") || e.getPlmId().startsWith("020") || e.getPlmId().startsWith("050"))).collect(Collectors.toList());
//            List<ApsWorkOrder> list = apsWorkOrderMapper.lambdaQuery().eq(ApsWorkOrder::getOrderId, order.getId()).notIn(ApsWorkOrder::getBomId, bomList.stream().map(BaseEntity::getId).collect(Collectors.toList())).list();
//
//            list.forEach(e->{
//                System.out.println(e.getPlmId());
//            });

//            throw SyExceptionUtils.e("有未排产的外来件，请先排产");

//        List<ReverseOrder> children = reverseOrderMapper.lambdaQuery()
//                .eq(ReverseOrder::getOrderId, order.getId())
//                .isNotNull(ReverseOrder::getParentId)
//                .list();
//        List<StationGroup> stationGroupList = stationGroupMapper.lambdaQuery().eq(StationGroup::getGroupId, group.getId()).list();
//        List<Station> stationList = stationMapper.selectBatchIds(stationGroupList.stream().map(StationGroup::getStationId).collect(Collectors.toList()));
//        for (ReverseOrder child : children) {
//            ReverseDetail rd = new ReverseDetail();
//            rd.setPhaseSeq(orderPhase.getPhaseSeq());
//            rd.setPhaseId(orderPhase.getId());
//            rd.setReverseOrderId(child.getId());
//            rd.setOrderId(child.getOrderId());
//            rd.setBomId(bom.getId());
//            rd.setBomPid(bom.getPid());
//            rd.setGroupCode(orderPhase.getWorkGroupNumber());
//            rd.setPlanStartSecond(0);
//            rd.setLevel(bom.getLevel());
//            rd.setStationGroupId(null);
//
//            rd.setGroupId(group.getId());
//
//            // 取出这个工序的真实的工作秒数
//            rd.setWorkCount(stationList.size());
//            rd.setWorkAbility(stationList.get(0).getWorkAbility());
//            rd.setWorkTime(orderPhase.getWorkTime());
//            rd.setTotalCount(null);
//
//            rd.setSplitNum(null);
//
//            rd.setProcessSecond(bom.getTotalCount()
//                    .multiply(new BigDecimal(orderPhase.getWorkTime()))
//                    .setScale(0, RoundingMode.UP)
//                    .intValue());
//
//            rd.setPlanEndSecond(rd.getPlanStartSecond() + rd.getProcessSecond());
//            rd.setAppendFlag(2);
//            reverseDetailMapper.insert(rd);
//        }
//
//
//        List<ApsWorkOrder> awoList = apsWorkOrderMapper.lambdaQuery()
//                .eq(ApsWorkOrder::getOrderId, order.getId())
//                .eq(ApsWorkOrder::getBomId, bom.getId())
//                .list();
//
//        if (awoList.isEmpty()) {
//            List<ApsWorkOrder> parentList = apsWorkOrderMapper.lambdaQuery()
//                    .eq(ApsWorkOrder::getOrderId, order.getId())
//                    .eq(ApsWorkOrder::getBomId, bom.getPid())
//                    .list();
//
//            List<ApsOrder> apsOrders = apsOrderMapper.selectBatchIds(parentList.stream().map(ApsWorkOrder::getApsOrderId).collect(Collectors.toList()));
//            Map<Integer, ApsOrder> collect = apsOrders.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));
//
//            for (ApsWorkOrder apsWorkOrder : parentList) {
//
//                LocalDateTime endDateTime = apsWorkOrder.getPlanStartDateTime();
//                ApsWorkOrder workOrder = MkBeanUtils.copyProperties(bom, ApsWorkOrder.class);
//
//                workOrder.setApsOrderId(collect.get(apsWorkOrder.getApsOrderId()).getId());
//                workOrder.setBomId(bom.getId());
//                workOrder.setBomPid(bom.getPid());
//                workOrder.setId(null);
//                workOrder.setPid(apsWorkOrder.getId());
//                workOrder.setStatus(2);
//                workOrder.setFinishCount(new BigDecimal(0));
//                workOrder.setTotalCount(bom.getTotalCount());
//                workOrder.setOrderCount(bom.getTotalCount().multiply(new BigDecimal(collect.get(apsWorkOrder.getApsOrderId()).getOrderQty())));
//                workOrder.setOrderType(order.getOrderType());
//                workOrder.setPlanStartDateTime(endDateTime);
//                workOrder.setPlanEndDateTime(endDateTime);
//                workOrder.setAppendFlag(2);
//
//                apsWorkOrderMapper.insert(workOrder);
//                awoList.add(workOrder);
//            }
//        }
//
//        // 判断有多少包
//        // 判断上级节点的时间
//        Integer smallTransfer = stationList.get(0).getSmallTransfer() == null ? 0 : stationList.get(0).getSmallTransfer();
//
//        List<ApsWorkDetail> apsWorkDetails = new ArrayList<>();
//
//        for (ApsWorkOrder workOrder : awoList) {
//
//            ApsOrder apsOrder = apsOrderMapper.selectById(workOrder.getApsOrderId());
//
//            ReverseDetail rd = new ReverseDetail();
//            rd.setPhaseSeq(orderPhase.getPhaseSeq());
//            rd.setPhaseId(orderPhase.getId());
//            rd.setReverseOrderId(apsOrder.getReverseId());
//            rd.setOrderId(workOrder.getOrderId());
//            rd.setBomId(bom.getId());
//            rd.setBomPid(bom.getPid());
//            rd.setGroupCode(orderPhase.getWorkGroupNumber());
//            rd.setPlanStartSecond(0);
//            rd.setLevel(bom.getLevel());
//            rd.setStationGroupId(null);
//
//            rd.setGroupId(group.getId());
//
//            // 取出这个工序的真实的工作秒数
//            rd.setWorkCount(stationList.size());
//            rd.setWorkAbility(stationList.get(0).getWorkAbility());
//            rd.setWorkTime(orderPhase.getWorkTime());
//            rd.setTotalCount(null);
//
//            rd.setSplitNum(null);
//
//            rd.setProcessSecond(bom.getTotalCount()
//                    .multiply(new BigDecimal(orderPhase.getWorkTime()))
//                    .setScale(0, RoundingMode.UP)
//                    .intValue());
//
//            rd.setPlanEndSecond(rd.getPlanStartSecond() + rd.getProcessSecond());
//            rd.setAppendFlag(2);
//            reverseDetailMapper.insert(rd);
//
//
//            ApsWorkDetail apsWorkDetail = new ApsWorkDetail();
//            apsWorkDetail.setOrderId(order.getId());
//            apsWorkDetail.setApsOrderId(workOrder.getApsOrderId());
//            apsWorkDetail.setApsWorkOrderId(workOrder.getId());
//            apsWorkDetail.setApsWorkOrderPid(workOrder.getPid());
//
//
//            if (projectConfig.getIgnorePhaseCodeList().contains(orderPhase.getPhaseCode())) {
//                continue;
//            }
//
//            apsWorkDetail.setPhaseId(orderPhase.getId());
//            apsWorkDetail.setWorkTime(orderPhase.getWorkTime());
//
//            if(apsWorkDetail.getPhaseCode().equals("YC")){
//                apsWorkDetail.setWorkTime(1);
//            }
//
//            apsWorkDetail.setPhaseSeq(orderPhase.getPhaseSeq());
//            apsWorkDetail.setPhaseCode(orderPhase.getPhaseCode());
//            apsWorkDetail.setPhaseName(orderPhase.getPhaseName());
//            apsWorkDetail.setPhaseCode(orderPhase.getPhaseCode());
//            apsWorkDetail.setMaterNo(orderPhase.getMaterNo());
//            apsWorkDetail.setMaterName(orderPhase.getMaterName());
//            apsWorkDetail.setGroupCode(orderPhase.getWorkGroupNumber());
//            apsWorkDetail.setOrderType(order.getOrderType());
//
//            // 从倒排表里取
//            apsWorkDetail.setPartCount(bom.getPartCount());
//            apsWorkDetail.setTotalCount(workOrder.getOrderCount());
//            apsWorkDetail.setGroupId(group.getId());
//            apsWorkDetail.setProcessCount(new BigDecimal(0));
//            apsWorkDetail.setFinishCount(new BigDecimal(0));
//            apsWorkDetail.setStatus(1);
////                apsWorkDetail.setStationGroupId(e.getStationGroupId());
//
//            apsWorkDetail.setDetailSeq(null);
//            apsWorkDetail.setApsOrderId(workOrder.getApsOrderId());
//            apsWorkDetail.setReverseDetailId(rd.getId());
//            apsWorkDetail.setAppendFlag(2);
//            apsWorkDetail.setPlanStartDateTime(workOrder.getPlanStartDateTime().minusSeconds(orderPhase.getWorkTime()));
//            apsWorkDetail.setPlanEndDateTime(workOrder.getPlanEndDateTime().minusSeconds(orderPhase.getWorkTime()));
//            apsWorkDetails.add(apsWorkDetail);
//
//        }
//
//        List<ApsWorkDetail> collect = apsWorkDetails.stream()
//                .flatMap(e -> {
//
//                    if (CollUtil.isEmpty(stationList)) {
//                        throw SyExceptionUtils.e("{}没有工位", e.getGroupCode());
//                    }
//                    if (smallTransfer == null || smallTransfer <= 0) {
//                        return Stream.of(e);
//                    }
//
//                    int div = e.getTotalCount().divide(new BigDecimal(smallTransfer), 0, RoundingMode.DOWN).intValue();
//
//                    BigDecimal subtract = e.getTotalCount().subtract(new BigDecimal(smallTransfer).multiply(new BigDecimal(div)));
//
//
//                    List<ApsWorkDetail> l = new ArrayList<>();
//
//                    for (int i = 0; i < div; i++) {
//                        ApsWorkDetail apsWorkDetail = MkBeanUtils.copyProperties(e, ApsWorkDetail.class);
//                        apsWorkDetail.setTotalCount(new BigDecimal(smallTransfer));
//                        l.add(apsWorkDetail);
//                    }
//
//                    if (subtract.compareTo(BigDecimal.ZERO) > 0) {
//                        ApsWorkDetail apsWorkDetail = MkBeanUtils.copyProperties(e, ApsWorkDetail.class);
//                        apsWorkDetail.setTotalCount(subtract);
//                        l.add(apsWorkDetail);
//                    }
//
//                    return l.stream();
//
//                })
//                .collect(Collectors.toList());
//
//        for (ApsWorkDetail apsWorkDetail : collect) {
//            apsWorkDetail.setType(1);
//            apsWorkDetailMapper.insert(apsWorkDetail);
//        }
//
//
////        Integer smallTransfer = stationList.get(0).getSmallTransfer() == null ? 0 : stationList.get(0).getSmallTransfer();
//
//
////        List<StationGroup> stationGroupList = stationGroupMapper.lambdaQuery().eq(StationGroup::getGroupId, group.getId()).list();
//        // 如果是激割或者火割，则推送套料
//        List<String> splitPhaseList = Arrays.asList("JG", "HG");
//        if(order.getOrderStatus() >= 6 && splitPhaseList.contains(orderPhase.getPhaseCode())){
//
//            for (ApsWorkDetail apsWorkDetail : collect) {
//
//                Map<Integer, ApsWorkOrder> workOrderMap = awoList.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));
//                ApsWorkOrder apsWorkOrder = workOrderMap.get(apsWorkDetail.getApsWorkOrderId());
//
//                List<ImportMbdDxf> importMbdDxfList = importMbdDxfMapper.lambdaQuery().in(ImportMbdDxf::getPlmid, bom.getPlmId()).list();
//                Map<String, ImportMbdDxf> mbdDxfMap = importMbdDxfList.stream().collect(Collectors.toMap(ImportMbdDxf::getPlmid, Function.identity(),(a,b)->b));
//
//                List<PlateStandard> plateStandardList = plateStandardMapper.lambdaQuery().in(PlateStandard::getNorm, apsWorkOrder.getStandards()).list();
//                Map<String, List<PlateStandard>> plateStandardMap = plateStandardList.stream().collect(Collectors.groupingBy(PlateStandard::getNorm));
//
//
//                lantekNestRule.saveDraw(apsWorkOrder, order, bom, mbdDxfMap);
//
//                ApsWorkOrder pa = apsWorkOrderMapper.selectById(apsWorkOrder.getPid());
//                ApsOrder apsOrder = apsOrderMapper.selectById(pa.getApsOrderId());
//                lantekNestRule.savePlan(apsWorkDetail, order, apsOrder, apsWorkOrder, pa, plateStandardMap, mbdDxfMap);
//
//            }
//            order.setPushStatus(4);
//            orderMapper.updateById(order);
//        }
    }

    @Transactional
    public void finishOrder(BaseIdReqVo reqVo) {
        Order order = orderMapper.selectById(reqVo.getId());
        if (order.getOrderStatus() != 8) {
            throw SyExceptionUtils.e("订单状态异常，只能关闭已开工的订单！");
        }
        order.setActualEndDateTime(LocalDateTime.now());
        order.setOrderStatus(10);
        orderMapper.updateById(order);
        List<ApsOrder> apsOrders = apsOrderMapper.lambdaQuery().eq(ApsOrder::getOrderId, order.getId()).lt(ApsOrder::getOrderStatus, 9).list();
        for (ApsOrder apsOrder : apsOrders) {
            apsOrder.setOrderStatus(10);
            apsOrder.setActualFinishTime(LocalDateTime.now());
            apsOrderMapper.updateById(apsOrder);
        }
        List<ApsWorkOrder> apsWorkOrders = apsWorkOrderMapper.lambdaQuery().eq(ApsWorkOrder::getOrderId, order.getId()).lt(ApsWorkOrder::getStatus, 4).list();
        for (ApsWorkOrder apsWorkOrder : apsWorkOrders) {
            apsWorkOrder.setActualEndDateTime(LocalDateTime.now());
            apsWorkOrder.setStatus(5);
            apsWorkOrderMapper.updateById(apsWorkOrder);
        }
        List<ApsWorkDetail> apsWorkDetails = apsWorkDetailMapper.lambdaQuery().eq(ApsWorkDetail::getOrderId, order.getId()).lt(ApsWorkDetail::getStatus, 4)
                .list();
        for (ApsWorkDetail apsWorkDetail : apsWorkDetails) {
            apsWorkDetail.setActualEndDateTime(LocalDateTime.now());
            apsWorkDetail.setStatus(5);
            apsWorkDetailMapper.updateById(apsWorkDetail);
            workDetailTaskMapper.lambdaUpdate().eq(WorkDetailTask::getApsWorkDetailId, apsWorkDetail.getId()).set(WorkDetailTask::getStatus, 5).update();
        }
        List<Order> orders = orderMapper.selectList(Wrappers.<Order>lambdaQuery().
                eq(Order::getConstructNo,  order.getConstructNo()).lt(Order::getOrderStatus, 9));
       if(!CollectionUtils.isEmpty( orders)&&orders.size()==1){
           List<Part> parts = partMapper.lambdaQuery().eq(Part::getConstructNo, order.getConstructNo()).list();
           for (Part part : parts) {
               partMapper.deleteById(part.getId());
           }
       }



    }

    @Transactional
    public void phaseAddMk(OrderPhaseAddMkReqVo reqVo) {
//        OrderPhase orderPhase = MkBeanUtils.copyProperties(reqVo, OrderPhase.class);
        Phase phase = phaseMapper.selectById(reqVo.getPhaseId());
        OrderBom bom = orderBomMapper.selectById(reqVo.getBomId());
        Group group = groupMapper.selectById(reqVo.getGroupId());
        List<OrderPhase> phaseList = orderPhaseMapper.lambdaQuery()
                .eq(OrderPhase::getBomId, bom.getId())
                .orderByAsc(OrderPhase::getPhaseSeq)
                .list();

        OrderPhase orderPhase = new OrderPhase();
        orderPhase.setOrderId(bom.getOrderId());
        orderPhase.setBomId(bom.getId());
        orderPhase.setWorkTime(reqVo.getWorkTime().multiply(new BigDecimal(60)).setScale(0, RoundingMode.UP).intValue());
        orderPhase.setPhaseName(phase.getName());
        orderPhase.setPhaseCode(phase.getMyCode());
        orderPhase.setMaterNo(bom.getPlmId());
        orderPhase.setMaterName(bom.getMaterName());
        orderPhase.setWorkGroupNumber(group.getMyCode());
        orderPhase.setOriWorkTime(orderPhase.getWorkTime());

        phaseList.add(reqVo.getPhaseIndex(), orderPhase);


        Map<String, Integer> phaseCount = new HashMap<>();
        for (int i = 0; i < phaseList.size(); i++) {
            phaseList.get(i).setPhaseCode(phaseList.get(i).getPhaseCode().replaceAll("\\d{2}$", ""));
            phaseList.get(i).setPhaseSeq(i + 1);

            Integer count = phaseCount.compute(phaseList.get(i).getPhaseCode(), (k, v) -> v == null ? 0 : v + 1);
            String phaseCodeCount = phaseList.get(i).getPhaseCode();
            if (count > 0) {
                phaseCodeCount = phaseList.get(i).getPhaseCode() + String.format("%02d", count);
            }
            phaseList.get(i).setPhaseCode(phaseCodeCount);


        }

        String workChain = phaseList.stream().map(OrderPhase::getPhaseCode).collect(Collectors.joining("-"));
        for (OrderPhase orderPhase1 : phaseList) {
            orderPhase1.setWorkChain(workChain);

            if (orderPhase1.getId() == null) {
                orderPhaseMapper.insert(orderPhase1);
            } else {
                orderPhaseMapper.updateById(orderPhase1);
            }
        }


        bom.setWorkChain(workChain);
        orderBomMapper.updateById(bom);

        Order order = orderMapper.selectById(bom.getOrderId());

        if (order.getOrderStatus() < 5) {
            return;
        }

        if (order.getOrderStatus() == 5) {
            order.setOrderStatus(3);
            orderMapper.updateById(order);
            return;
        }

        List<ApsWorkOrder> awoList = apsWorkOrderMapper.lambdaQuery()
                .eq(ApsWorkOrder::getOrderId, order.getId())
                .eq(ApsWorkOrder::getBomId, bom.getId())
                .list();

        List<Station> stationList = stationMapper.lambdaQuery().eq(Station::getGroupId, group.getId()).list();
        Integer smallTransfer = stationList.get(0).getSmallTransfer() == null ? 0 : stationList.get(0).getSmallTransfer();

        List<ApsWorkDetail> apsWorkDetails = new ArrayList<>();
        for (ApsWorkOrder workOrder : awoList) {
            ApsWorkDetail apsWorkDetail = new ApsWorkDetail();
            apsWorkDetail.setOrderId(order.getId());
            apsWorkDetail.setApsOrderId(workOrder.getApsOrderId());
            apsWorkDetail.setApsWorkOrderId(workOrder.getId());
            apsWorkDetail.setApsWorkOrderPid(workOrder.getPid());

            if (projectConfig.getIgnorePhaseCodeList().contains(orderPhase.getPhaseCode())) {
                continue;
            }

            apsWorkDetail.setPhaseId(orderPhase.getId());
            apsWorkDetail.setWorkTime(orderPhase.getWorkTime());

            apsWorkDetail.setPhaseSeq(orderPhase.getPhaseSeq());
            apsWorkDetail.setPhaseCode(orderPhase.getPhaseCode());
            apsWorkDetail.setPhaseName(orderPhase.getPhaseName());
            apsWorkDetail.setPhaseCode(orderPhase.getPhaseCode());
            apsWorkDetail.setMaterNo(orderPhase.getMaterNo());
            apsWorkDetail.setMaterName(orderPhase.getMaterName());
            apsWorkDetail.setGroupCode(orderPhase.getWorkGroupNumber());
            apsWorkDetail.setOrderType(order.getOrderType());

            // 从倒排表里取
            apsWorkDetail.setPartCount(bom.getPartCount());
            apsWorkDetail.setTotalCount(workOrder.getOrderCount());
            apsWorkDetail.setGroupId(group.getId());
            apsWorkDetail.setProcessCount(new BigDecimal(0));
            apsWorkDetail.setFinishCount(new BigDecimal(0));
            apsWorkDetail.setStatus(2);
//                apsWorkDetail.setStationGroupId(e.getStationGroupId());

            apsWorkDetail.setDetailSeq(null);
            apsWorkDetail.setApsOrderId(workOrder.getApsOrderId());
            apsWorkDetail.setReverseDetailId(null);
            apsWorkDetail.setAppendFlag(2);
            apsWorkDetail.setPlanStartDateTime(workOrder.getPlanStartDateTime().minusSeconds(orderPhase.getWorkTime()));
            apsWorkDetail.setPlanEndDateTime(workOrder.getPlanStartDateTime());
            apsWorkDetail.setType(2);
            apsWorkDetail.setPlmId(bom.getPlmId());
            apsWorkDetails.add(apsWorkDetail);
        }

        List<ApsWorkDetail> collect = apsWorkDetails.stream()
                .flatMap(e -> {

                    if (CollUtil.isEmpty(stationList)) {
                        throw SyExceptionUtils.e("{}没有工位", e.getGroupCode());
                    }

//                    e.setStationGroupId(stationGroupList.get(0).getId());
                    e.setStationId(stationList.get(0).getId());
                    e.setChangTime(stationList.get(0).getChangTime());
                    e.setEnterTime(stationList.get(0).getEnterTime());
                    e.setOutTime(stationList.get(0).getOutTime());

                    if (e.getChangTime() == null) {
                        e.setChangTime(0);
                    }

                    if (e.getEnterTime() == null) {
                        e.setEnterTime(0);
                    }

                    if (e.getOutTime() == null) {
                        e.setOutTime(0);
                    }

                    if (smallTransfer <= 0) {
                        e.setTotalWorkTime(orderPhase.getWorkTime() * e.getTotalCount().intValue());
                        return Stream.of(e);
                    }

                    int div = e.getTotalCount().divide(new BigDecimal(smallTransfer), 0, RoundingMode.DOWN).intValue();

                    BigDecimal subtract = e.getTotalCount().subtract(new BigDecimal(smallTransfer).multiply(new BigDecimal(div)));


                    List<ApsWorkDetail> l = new ArrayList<>();

                    for (int i = 0; i < div; i++) {
                        ApsWorkDetail apsWorkDetail = MkBeanUtils.copyProperties(e, ApsWorkDetail.class);
                        apsWorkDetail.setTotalCount(new BigDecimal(smallTransfer));
                        apsWorkDetail.setTotalWorkTime(orderPhase.getWorkTime() * apsWorkDetail.getTotalCount().intValue());
                        l.add(apsWorkDetail);
                    }

                    if (subtract.compareTo(BigDecimal.ZERO) > 0) {
                        ApsWorkDetail apsWorkDetail = MkBeanUtils.copyProperties(e, ApsWorkDetail.class);
                        apsWorkDetail.setTotalCount(subtract);
                        apsWorkDetail.setTotalWorkTime(orderPhase.getWorkTime() * apsWorkDetail.getTotalCount().intValue());
                        l.add(apsWorkDetail);
                    }

                    return l.stream();

                })
                .collect(Collectors.toList());

        List<Integer> workOrderIdList = awoList.stream().map(BaseEntity::getId).distinct().collect(Collectors.toList());
        List<ApsWorkDetail> workDetailList = apsWorkDetailMapper.lambdaQuery().in(ApsWorkDetail::getApsWorkOrderId, workOrderIdList).list();
        Map<Integer, OrderPhase> orderPhaseIdMap = phaseList.stream().collect(Collectors.toMap(e -> e.getId(), Function.identity()));

        for (ApsWorkDetail apsWorkDetail : workDetailList) {
            if (apsWorkDetail.getPhaseId() == null) {
                continue;
            }
            OrderPhase temp = orderPhaseIdMap.get(apsWorkDetail.getPhaseId());
            if (temp == null) {
                continue;
            }

            ApsWorkDetail awd = new ApsWorkDetail();
            awd.setPhaseCode(apsWorkDetail.getPhaseCode());
            awd.setId(apsWorkDetail.getId());
            awd.setPhaseSeq(temp.getPhaseSeq());
            apsWorkDetailMapper.updateById(awd);

        }

        for (ApsWorkOrder apsWorkOrder : awoList) {
            ApsWorkOrder awo = new ApsWorkOrder();
            awo.setId(apsWorkOrder.getId());
            awo.setWorkChain(workChain);
            apsWorkOrderMapper.updateById(awo);
        }

        apsWorkDetailMapper.insertBatch(collect);

    }

    public BaseListResVo<String> listCode(OrderListReqVo reqVo) {
        LambdaQueryWrapper<Order> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StringUtils.hasText(reqVo.getOrderCode()), Order::getOrderCode, reqVo.getOrderCode());
        wrapper.like(StringUtils.hasText(reqVo.getConstructNo()), Order::getConstructNo, reqVo.getConstructNo());
        if (reqVo.getOrderType() == null) {
            wrapper.in(Order::getOrderType, 1, 3, 4);
        } else {
            wrapper.eq(Order::getOrderType, reqVo.getOrderType());
        }
        wrapper.like(reqVo.getSerialCode() != null, Order::getSerialCode, reqVo.getSerialCode());
        wrapper.eq(reqVo.getOrderStatus() != null, Order::getOrderStatus, reqVo.getOrderStatus());
        wrapper.in(reqVo.getOrderStatus() == null, Order::getOrderStatus, 6, 7, 8);
        wrapper.like(StringUtils.hasText(reqVo.getMaterCode()), Order::getMaterCode, reqVo.getMaterCode());
        wrapper.like(StringUtils.hasText(reqVo.getMaterName()), Order::getMaterName, reqVo.getMaterName());
        wrapper.orderByDesc(Order::getCreateDateTime);
        List<Order> orderPage = orderMapper.selectList(wrapper);
        List<String> collect = orderPage.stream().map(Order::getConstructNo).distinct().collect(Collectors.toList());
        return new BaseListResVo<>(collect);
    }

    @Transactional
    public void mbdPub(PlandOrderAddReqVo reqVo) {
        Order order = orderMapper.selectById(reqVo.getId());
        //   Order order  = orderMapper.selectOneAll(reqVo.getId());

        if (order == null) {
            throw SyExceptionUtils.e("订单不存在");
        }

        if (order.getOrderType() != 2) {
            throw SyExceptionUtils.e("不是MBD订单无法发布");
        }

        if (order.getOrderStatus() >= 2) {
            throw SyExceptionUtils.e("订单已发布");
        }

        Order one = orderMapper.lambdaQuery()
                .in(Order::getOrderType, 2, 5)
                .ge(Order::getOrderStatus, 2)
                .eq(Order::getConstructNo, reqVo.getConstructNo())
                .last(" limit 1 ")
                .one();
        Order oo = orderMapper.lambdaQuery().eq(Order::getPlannedMonth, reqVo.getPlannedMonth()).isNotNull(Order::getSeq).orderByDesc(Order::getSeq).last(" limit 1 ").one();
        Order o = new Order();
        o.setId(order.getId());
        o.setFrameType(reqVo.getFrameType());
        o.setConstructNo(reqVo.getConstructNo());
        o.setPlannedMonth(reqVo.getPlannedMonth());
        o.setSeq(oo == null ? 1 : oo.getSeq() + 1);
        o.setOrderQty(reqVo.getOrderQty());
        o.setPublishDateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        o.setSuffix(order.getSuffix());
        o.setOrderStatus(2);

        if (one == null) {
            orderMapper.updateById(o);
            return;
        }

        if (!one.getPlannedMonth().equals(reqVo.getPlannedMonth())) {
            throw SyExceptionUtils.e("计划月份不一致,目标月份:{},当前月份:{}", one.getPlannedMonth(), reqVo.getPlannedMonth());
        }

        Integer minSeq = one.getSeq();

        List<Order> orderList = orderMapper.lambdaQuery()
                .eq(Order::getPlannedMonth, reqVo.getPlannedMonth())
                .in(Order::getOrderType, 2, 5)
                .ge(Order::getOrderStatus, 2)
                .ge(Order::getSeq, minSeq)
                .list();

        List<Order> eqOrder = orderList.stream().filter(e -> e.getConstructNo().equals(reqVo.getConstructNo())).collect(Collectors.toList());

        List<Order> neOrder = orderList.stream().filter(e -> !e.getConstructNo().equals(reqVo.getConstructNo())).collect(Collectors.toList());

        Map<String, Integer> orderTypes = new HashMap<>();
        orderTypes.put("D", 1);
        orderTypes.put("Z", 2);
        orderTypes.put("Y", 3);
        orderTypes.put("C", 4);
        orderTypes.put("L", 5);
        orderTypes.put("T", 5);
        orderTypes.put("B", 7);

        eqOrder.add(o);
        eqOrder.sort(Comparator.comparing(e -> orderTypes.get(e.getSuffix())));

        neOrder.sort(Comparator.comparing(Order::getSeq));

        eqOrder.addAll(neOrder);
        for (int i = 0; i < eqOrder.size(); i++) {
            Order ooo = eqOrder.get(i);
            ooo.setSeq(i + minSeq);
            orderMapper.updateById(ooo);
        }

    }

    public BasePageResVo<OrderListResVo> listMbd(OrderListReqVo reqVo) {
        QueryWrapper<Order> wrapper = Wrappers.query();
        wrapper.like(StringUtils.hasText(reqVo.getOrderCode()), "t.order_code", reqVo.getOrderCode());
        wrapper.like(StringUtils.hasText(reqVo.getConstructNo()), "t.construct_no", reqVo.getConstructNo());
        if (reqVo.getOrderType() == null) {
            wrapper.in("t.order_type", 5);
            wrapper.or(wr -> wr.eq("t.order_type", 2).ge("t.order_status", 2));
        } else {
            wrapper.eq("t.order_type", reqVo.getOrderType());
        }
        wrapper.like(reqVo.getSerialCode() != null, "t.serial_code", reqVo.getSerialCode());
        wrapper.eq(reqVo.getOrderStatus() != null, "t.order_status", reqVo.getOrderStatus());
        wrapper.ge(reqVo.getOrderStatusGe() != null, "t.order_status", reqVo.getOrderStatusGe());
        wrapper.like(StringUtils.hasText(reqVo.getMaterCode()), "t.mater_code", reqVo.getMaterCode());
        wrapper.like(StringUtils.hasText(reqVo.getMaterName()), "t.mater_name", reqVo.getMaterName());
        wrapper.orderByDesc("t.create_date_time");

        Page<Order> orderPage = orderMapper.selectMbdPage(reqVo.toPage(), wrapper);

        BasePageResVo<OrderListResVo> orderListResVoBasePageResVo = BasePageResVo.of(orderPage, OrderListResVo.class);
        for (OrderListResVo datum : orderListResVoBasePageResVo.getData()) {
            datum.setConstructNo(datum.getConstructNo());
            datum.setFrameType(datum.getFrameType());
            datum.setDeliveryDate(datum.getDeliveryDateTime());
            datum.setFactoryCode("170");
        }
        return orderListResVoBasePageResVo;
    }

    @Transactional
    public void updatePlanedSeq(OrderUpdatePlaneSeqReqVo reqVo) {

        List<Integer> ids = reqVo.getIds();
        if (!("seq".equals(reqVo.getSort()) && "asc".equals(reqVo.getOrder()))) {
            Collections.reverse(ids);
        }

        List<Order> orders = orderMapper.selectBatchIds(ids);
        Map<Integer, Order> orderIdMap = orders.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));
        LinkedHashMap<String, List<Order>> orderMap = new LinkedHashMap<>();

        for (Integer orderId : ids) {
            Order order = orderIdMap.get(orderId);
            orderMap.computeIfAbsent(order.getConstructNo(), k -> new ArrayList<>()).add(order);
        }

        Map<String, Integer> orderTypes = new HashMap<>();
        orderTypes.put("D", 1);
        orderTypes.put("Z", 2);
        orderTypes.put("Y", 3);
        orderTypes.put("C", 4);
        orderTypes.put("L", 5);
        orderTypes.put("T", 6);
        orderTypes.put("B", 7);

        int i = 1;
        for (String key : orderMap.keySet()) {
            List<Order> orderList = orderMap.get(key);
            orderList.sort(Comparator.comparing(e -> orderTypes.get(e.getSuffix())));
            for (Order order : orderList) {
                Order o = new Order();
                o.setId(order.getId());
                o.setSeq(i++);
                orderMapper.updateById(o);
            }
        }

    }

    @Transactional
    public void append(OrderAppendReqVo reqVo) {

        System.out.println(JsonUtils.toJsonString(reqVo));

        ImportErpBom currentBom = importErpBomMapper.selectById(reqVo.getId());
        if (currentBom == null) {
            throw SyExceptionUtils.e("当前BOM不存在");
        }

        if ("R".equals(currentBom.getStatusId())) {
            throw SyExceptionUtils.e("该节点状态异常");
        }

        ImportErpOrder importErpOrder = importErpOrderMapper.selectById(currentBom.getErpOrderId());

        // 获取所有的子节点
        List<ImportErpBom> allBomTree = findAllTree(importErpOrder);

        // 获取可用的的子节点
        List<ImportErpBom> bomChildren = findBomChildren(currentBom);

        List<String> materCodeList = bomChildren.stream().map(ImportErpBom::getMaterialCode).collect(Collectors.toList());

        // 获取所有的物料信息组成Map，供BOM使用
        List<ImportErpMater> materList = getMaterMap(currentBom.getErpOrderId(), materCodeList);

        // 获取所有的工单信息组成Map，供BOM使用
        List<ImportErpWorkOrder> erpWorkOrderList = getWorkOrderMap(currentBom.getErpOrderId(), materCodeList);

        // 获取所有的工单明细组成Map，供BOM使用
        List<ImportErpWorkOrderDetail> workOrderDetailList = getWorkOrderDetailMap(currentBom.getErpOrderId(), materCodeList);

        // 获取所有的工序映射，供BOM使用
        List<ImportErpMapping> importErpMappings = importErpMappingMapper.selectList(null);

        // 转换订单
        Optional<ImportErpMater> first = materList.stream().filter(e -> e.getMaterialCode().equals(currentBom.getMaterialCode())).findFirst();
        if (!first.isPresent()) {
            throw SyExceptionUtils.e("找不到对应的物料信息");
        }

        List<OrderExternalSyncErrorResVo> errorList = new ArrayList<>();

        Order order = conversionOrder(importErpOrder, currentBom, first.get(), errorList);

        // 判断是否重复
        String pattern = ".+" + WorkshopProp.PH_PATTERN;
        List<String> assList = bomChildren.stream()
                .map(ImportErpBom::getGraphNo)
                .filter(graphNo -> graphNo.matches(pattern))
                .distinct()
                .collect(Collectors.toList());


        Map<String, ImportErpBom> collect = allBomTree.stream().collect(Collectors.toMap(ImportErpBom::getMaterialCode, Function.identity(), (e1, e2) -> e1));
        ImportErpBom parentTemp = collect.get(currentBom.getMaterialCode());
        while (parentTemp != null) {
            assList.add(parentTemp.getGraphNo());
            parentTemp = collect.get(parentTemp.getPmCode());
        }


        // 判断是否重复导入，
        ArrayList<String> dyz = Lists.newArrayList("D", "Y", "Z");
        if (order.getOrderType().equals(1) && dyz.contains(order.getSuffix())) {
            throw SyExceptionUtils.e("该订单已重复或者重叠，请勿重复同步。");
        }

        if (dyz.contains(order.getSuffix())) {
            Integer ct = orderMapper.lambdaQuery()
                    .eq(Order::getConstructNo, order.getConstructNo())
                    .in(Order::getMaterCode, assList)
                    .count();
            if (ct > 0) {
                throw SyExceptionUtils.e("该订单已重复或者重叠，请勿重复同步。");
            }
        } else {
            order = orderMapper.lambdaQuery().eq(Order::getConstructNo, order.getConstructNo()).eq(Order::getSuffix, order.getSuffix()).one();
            Integer count = orderBomMapper.lambdaQuery().eq(OrderBom::getOrderId, order.getId()).eq(OrderBom::getErpCode, currentBom.getMaterialCode()).eq(OrderBom::getLevel, 2).count();
            if (count > 0) {
                throw SyExceptionUtils.e("该订单已重复或者重叠，请勿重复同步。");
            }
        }

        // 转换BOM
        List<OrderBom> orderBomList = conversionBom(order, importErpOrder, allBomTree, bomChildren, materList, erpWorkOrderList, workOrderDetailList, importErpMappings, errorList);
        orderBomList.removeIf(e -> e.getLevel() == 1);

        // 转换零件
        savePart(orderBomList, order, materList, erpWorkOrderList, workOrderDetailList, importErpMappings, errorList);

        // 转换工序
        List<OrderPhase> orderPhaseList = conversionPhase(order, orderBomList, workOrderDetailList, importErpMappings, errorList);
        savePhase(orderPhaseList);

        // 转换并保存辅料
        conversionAndSaveAccessories(order, orderBomList, errorList, currentBom, orderPhaseList);
//        saveAccessories(orderPhaseList);

        String key = "mom-srv-aps:order-sync:error:" + order.getConstructNo() + ":" + first.get().getPlmId();
        if (CollUtil.isNotEmpty(errorList)) {
            // 存redis
            stringRedisTemplate.opsForValue()
                    .set(key, JsonUtils.toJsonString(errorList), 10, TimeUnit.DAYS);

            throw SyExceptionUtils.e("同步失败，请查看Excel的错误信息");
        }
        stringRedisTemplate.delete(key);

        if (order.getOrderStatus() <= 3) {
            return;
        }

        if (order.getOrderStatus() < 6) {
            order.setOrderStatus(3);
            orderMapper.updateById(order);
            return;
        }

        final Order finalOrder = order;
        List<ApsWorkOrder> allWorkOrder = new ArrayList<>();
        orderBomList.sort(Comparator.comparingInt(OrderBom::getLevel));

        for (OrderBom orderBom : orderBomList) {
            List<ApsWorkOrder> parentList = apsWorkOrderMapper.lambdaQuery().eq(ApsWorkOrder::getBomId, orderBom.getPid()).list();
            Map<Integer, ApsWorkOrder> workOrderMap = parentList.stream().collect(Collectors.toMap(ApsWorkOrder::getApsOrderId, e -> e));

            // 生成ApsWorkOrder
            List<ApsOrder> apsOrderList = apsOrderMapper.lambdaQuery().eq(ApsOrder::getOrderId, order.getId()).list();
            List<ApsWorkOrder> apsWorkOrderList = Stream.of(orderBom)
                    .map(e -> {

                        ApsWorkOrder workOrder = MkBeanUtils.copyProperties(e, ApsWorkOrder.class);
                        workOrder.setBomId(e.getId());
                        workOrder.setBomPid(e.getPid());
                        workOrder.setId(null);
                        workOrder.setStatus(1);
                        workOrder.setFinishCount(new BigDecimal(0));
                        workOrder.setTotalCount(e.getTotalCount());
                        workOrder.setOrderType(finalOrder.getOrderType());
                        workOrder.setPlmId(e.getPlmId());
//                    apsBom.setApsOrderId(apsOrder.getId());
//                    apsBom.setOrderCount(e.getTotalCount().multiply(new BigDecimal(apsOrder.getOrderQty())));
                        return workOrder;
                    })
                    .flatMap(e ->
//                        ApsWorkOrder apsWorkOrder = workOrderMap.get(e.getPid());
                                    apsOrderList
                                            .stream()
                                            .map(e1 -> {
                                                ApsWorkOrder awo = new ApsWorkOrder();
                                                BeanUtils.copyProperties(e, awo);
                                                awo.setApsOrderId(e1.getId());
                                                awo.setOrderCount(e.getTotalCount().multiply(new BigDecimal(e1.getOrderQty())));
                                                awo.setPlanStartDateTime(LocalDateTime.now());
                                                awo.setPlanEndDateTime(LocalDateTime.now());
                                                awo.setPid(workOrderMap.get(e1.getId()).getId());
                                                return awo;
                                            })
                    )
                    .collect(Collectors.toList());


            allWorkOrder.addAll(apsWorkOrderList);
            apsWorkOrderMapper.insertBatch(apsWorkOrderList);

        }

//        apsWorkOrderMapper.insertBatch(allWorkOrder);

        // 把 apsWorkOrderList 赋值，并推送到立体库
        wmsService.partProcurement(order.getId(), 0);

        Map<Integer, List<OrderPhase>> orderPhaseMap = orderPhaseList.stream().collect(Collectors.groupingBy(OrderPhase::getBomId));
        List<ApsWorkOrder> hasPhaseWorkOrder = allWorkOrder.stream().filter(e -> !e.getWorkChain().equals("WL")).collect(Collectors.toList());
        Map<Integer, OrderBom> orderBomMap = orderBomList.stream().collect(Collectors.toMap(BaseEntity::getId, e -> e));
        List<String> groupCodeList = orderPhaseList.stream().map(OrderPhase::getWorkGroupNumber).distinct().collect(Collectors.toList());
        List<Group> groupList = groupMapper.lambdaQuery().in(Group::getMyCode, groupCodeList).list();
        Map<String, Group> groupCodeMap = groupList.stream().collect(Collectors.toMap(Group::getMyCode, e -> e));
        List<ApsWorkDetail> apsWorkDetails = new ArrayList<>();


        for (ApsWorkOrder workOrder : hasPhaseWorkOrder) {
            ApsOrder apsOrder = apsOrderMapper.selectById(workOrder.getApsOrderId());


            List<OrderPhase> orderPhases = orderPhaseMap.get(workOrder.getBomId());

            OrderBom bom = orderBomMap.get(workOrder.getBomId());
            for (OrderPhase currentPhase : orderPhases) {
                Group group = groupCodeMap.get(currentPhase.getWorkGroupNumber());

                ApsWorkDetail apsWorkDetail = new ApsWorkDetail();
                apsWorkDetail.setOrderId(order.getId());
                apsWorkDetail.setApsOrderId(workOrder.getApsOrderId());
                apsWorkDetail.setApsWorkOrderId(workOrder.getId());
                apsWorkDetail.setApsWorkOrderPid(workOrder.getPid());
                if (projectConfig.getIgnorePhaseCodeList().contains(currentPhase.getPhaseCode())) {
                    continue;
                }

                apsWorkDetail.setPhaseId(currentPhase.getId());
                apsWorkDetail.setWorkTime(currentPhase.getWorkTime());

                apsWorkDetail.setPhaseSeq(currentPhase.getPhaseSeq());
                apsWorkDetail.setPhaseCode(currentPhase.getPhaseCode());
                apsWorkDetail.setPhaseName(currentPhase.getPhaseName());
                apsWorkDetail.setPhaseCode(currentPhase.getPhaseCode());
                apsWorkDetail.setMaterNo(currentPhase.getMaterNo());
                apsWorkDetail.setMaterName(currentPhase.getMaterName());
                apsWorkDetail.setPlmId(bom.getPlmId());
                apsWorkDetail.setGroupCode(currentPhase.getWorkGroupNumber());
                apsWorkDetail.setOrderType(order.getOrderType());

                // 从倒排表里取
                apsWorkDetail.setPartCount(bom.getPartCount());
                apsWorkDetail.setTotalCount(workOrder.getOrderCount());
                apsWorkDetail.setGroupId(group.getId());
                apsWorkDetail.setProcessCount(new BigDecimal(0));
                apsWorkDetail.setFinishCount(new BigDecimal(0));
                apsWorkDetail.setStatus(1);


                apsWorkDetail.setDetailSeq(null);
                apsWorkDetail.setApsOrderId(workOrder.getApsOrderId());

                apsWorkDetail.setTotalWorkTime(apsWorkDetail.getTotalCount().multiply(new BigDecimal(currentPhase.getWorkTime())).intValue());

                apsWorkDetail.setReverseDetailId(null);
                apsWorkDetail.setAppendFlag(2);
                apsWorkDetail.setPlanEndDateTime(workOrder.getPlanStartDateTime());
                apsWorkDetail.setPlanStartDateTime(apsWorkDetail.getPlanEndDateTime().minusSeconds(apsWorkDetail.getTotalWorkTime()));
                apsWorkDetails.add(apsWorkDetail);
            }

        }


        List<Station> stationListTemp = stationMapper.lambdaQuery().in(Station::getGroupId, groupList.stream().map(BaseEntity::getId).collect(Collectors.toList())).list();
        Map<Integer, Group> ttt = groupList.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));
        Map<String, List<Station>> map = stationListTemp.stream().collect(Collectors.groupingBy(e -> ttt.get(e.getGroupId()).getMyCode()));
        List<ApsWorkDetail> collect12 = apsWorkDetails.stream()
                .flatMap(e -> {

                    List<Station> stationList = map.get(e.getGroupCode());
                    int smallTransfer = stationList.get(0).getSmallTransfer() == null ? 0 : stationList.get(0).getSmallTransfer();

                    if (CollUtil.isEmpty(stationList)) {
                        throw SyExceptionUtils.e("{}没有工位", e.getGroupCode());
                    }
                    e.setStationId(stationList.get(0).getId());

                    if (smallTransfer <= 0) {
                        return Stream.of(e);
                    }

                    int div = e.getTotalCount().divide(new BigDecimal(smallTransfer), 0, RoundingMode.DOWN).intValue();

                    BigDecimal subtract = e.getTotalCount().subtract(new BigDecimal(smallTransfer).multiply(new BigDecimal(div)));


                    List<ApsWorkDetail> l = new ArrayList<>();

                    for (int i = 0; i < div; i++) {
                        ApsWorkDetail apsWorkDetail = MkBeanUtils.copyProperties(e, ApsWorkDetail.class);
                        apsWorkDetail.setTotalCount(new BigDecimal(smallTransfer));
                        apsWorkDetail.setStationId(stationList.get(0).getId());
                        l.add(apsWorkDetail);
                    }

                    if (subtract.compareTo(BigDecimal.ZERO) > 0) {
                        ApsWorkDetail apsWorkDetail = MkBeanUtils.copyProperties(e, ApsWorkDetail.class);
                        apsWorkDetail.setTotalCount(subtract);
                        apsWorkDetail.setStationId(stationList.get(0).getId());
                        l.add(apsWorkDetail);
                    }

                    return l.stream();

                })
                .collect(Collectors.toList());


        for (ApsWorkDetail apsWorkDetail : collect12) {
            apsWorkDetail.setType(2);
            apsWorkDetail.setStatus(2);
        }
        apsWorkDetailMapper.insertBatch(collect12);

        List<ApsWorkDetail> splitPhaseList = collect12.stream().filter(e -> e.getPhaseCode().equals("JG") || e.getPhaseCode().equals("HG")).collect(Collectors.toList());
        if (CollUtil.isEmpty(splitPhaseList)) {
            return;
        }

        // 发送到海克思康,强制推送
        try {
            planAdd(splitPhaseList);
        } catch (Exception e) {
            log.info("补充零件推送计划异常。");
        }

        List<String> nestPlanIds = splitPhaseList.stream().map(e -> {
            return String.valueOf(e.getId());
        }).collect(Collectors.toList());

        List<SinoCamPushPlan> pushPlanList = sinoCamPushPlanMapper.lambdaQuery().in(SinoCamPushPlan::getNestPlanId, nestPlanIds).list();

        List<HexagonPackagePush> hexPushList = hexagonPackagePushMapper.lambdaQuery().eq(HexagonPackagePush::getOrderId, order.getId()).list();
        if (CollUtil.isEmpty(hexPushList)) {
            return;
        }
        NestProPushHexReqVo hexReqVo = new NestProPushHexReqVo();
        hexReqVo.setNestPlanId(nestPlanIds);
        hexReqVo.setOrderId(order.getId());
        hexReqVo.setCustName(hexPushList.get(0).getCustName());
        hexReqVo.setCustCode(hexPushList.get(0).getCustCode());
        hexReqVo.setMesOrderId(hexPushList.get(0).getMesOrderId());
        hexReqVo.setMesOrderCode(hexPushList.get(0).getMesOrderCode());

        List<ApsNestHexagonItemReqVo> items = hexPushList.stream().map(e -> {
            ApsNestHexagonItemReqVo item = new ApsNestHexagonItemReqVo();
            item.setDeliveryDate(e.getEndDate());
            item.setPkgCode(e.getPackageCode());
            return item;
        }).collect(Collectors.toList());
        hexReqVo.setItem(items);

        List<HexagonPackagePush> packagePushList = hexagonNestRule.converterAndSave(hexReqVo, pushPlanList);

        hexagonNestRule.sendToMesAll(hexReqVo, packagePushList);

    }


    public void planAdd(List<ApsWorkDetail> apsWorkDetailList) {

        if (CollUtil.isEmpty(apsWorkDetailList)) {
            return;
        }

        List<Integer> orderIds = apsWorkDetailList.stream().map(ApsWorkDetail::getOrderId).collect(Collectors.toList());

        List<ApsOrder> apsOrders = apsOrderMapper.lambdaQuery().in(ApsOrder::getOrderId, orderIds).list();
        Map<Integer, ApsOrder> apsOrderIdMap = apsOrders.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        // 取 ID
        List<ApsWorkOrder> apsWorkOrders = apsWorkOrderMapper.selectBatchIds(apsWorkDetailList.stream().map(ApsWorkDetail::getApsWorkOrderId).distinct().collect(Collectors.toList()));
        Map<Integer, ApsWorkOrder> apsWorkOrderIdMap = apsWorkOrders.stream().collect(Collectors.toMap(ApsWorkOrder::getId, Function.identity()));

        // 取 PID
        List<ApsWorkOrder> parentApsWorkOrders = apsWorkOrderMapper.selectBatchIds(apsWorkDetailList.stream().map(ApsWorkDetail::getApsWorkOrderPid).distinct().collect(Collectors.toList()));
        Map<Integer, ApsWorkOrder> apsWorkOrderPidMap = parentApsWorkOrders.stream().collect(Collectors.toMap(ApsWorkOrder::getId, Function.identity()));

        // 获取工厂信息
        List<Factory> factoryList = factoryMapper.selectList(null);
        Map<Integer, Factory> factoryMap = factoryList.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        List<Order> orderList = orderMapper.lambdaQuery().in(BaseEntity::getId, orderIds).list();

        // 保存计划信息
        savePlan(apsWorkDetailList, factoryMap, orderList, apsOrderIdMap, apsWorkOrderPidMap, apsWorkOrderIdMap);

    }

    public void savePlan(List<ApsWorkDetail> apsWorkDetailList, Map<Integer, Factory> factoryMap, List<Order> orderList, Map<Integer, ApsOrder> apsOrderIdMap, Map<Integer, ApsWorkOrder> apsWorkOrderPidMap, Map<Integer, ApsWorkOrder> apsWorkOrderIdMap) {

        List<SinoCamPushDrawing> sinoCamPushPushDrawList = sinoCamPushDrawingMapper.lambdaQuery().in(SinoCamPushDrawing::getPartId, apsWorkDetailList.stream().map(ApsWorkDetail::getPlmId).collect(Collectors.toList())).list();
        Map<String, SinoCamPushDrawing> sinoCamPushPushDrawMap = sinoCamPushPushDrawList.stream().collect(Collectors.toMap(SinoCamPushDrawing::getPartId, Function.identity(), (a, b) -> b));

        Map<Integer, Order> orderMap = orderList.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        List<ApsWorkOrder> allApsWorkOrder = apsWorkOrderMapper.lambdaQuery().in(ApsWorkOrder::getOrderId, orderList.stream().map(Order::getId).collect(Collectors.toList())).list();
        Map<Integer, List<ApsWorkOrder>> orderApsWorkOrder = allApsWorkOrder.stream().collect(Collectors.groupingBy(ApsWorkOrder::getOrderId));
        Map<Integer, Map<Integer, ApsWorkOrder>> allApsWorkOrderMap = new HashMap<>();
        for (Integer orderId : orderApsWorkOrder.keySet()) {
            List<ApsWorkOrder> orderApsWorkOrderMap = orderApsWorkOrder.get(orderId);
            Map<Integer, ApsWorkOrder> apsWorkOrderMap = orderApsWorkOrderMap.stream().collect(Collectors.toMap(ApsWorkOrder::getId, Function.identity()));
            allApsWorkOrderMap.put(orderId, apsWorkOrderMap);
        }

        List<SinoCamPushPlan> pushPlans = sinoCamPushPlanMapper.lambdaQuery().in(SinoCamPushPlan::getOrderId, orderList.stream().map(Order::getId).collect(Collectors.toList())).list();
        Map<String, SinoCamPushPlan> pushPlanMap = pushPlans.stream().collect(Collectors.toMap(SinoCamPushPlan::getNestPlanId, Function.identity()));

        List<SinoCamPushPlan> pushPlanList = new ArrayList<>();
        // 构建推送参数和数据库记录信息
        for (ApsWorkDetail apsWorkDetail : apsWorkDetailList) {

            SinoCamPushPlan pushPlan = new SinoCamPushPlan();

            ApsWorkOrder current = apsWorkOrderIdMap.get(apsWorkDetail.getApsWorkOrderId());
            ApsWorkOrder parent = apsWorkOrderPidMap.get(current.getPid());
            ApsOrder apsOrder = apsOrderIdMap.get(apsWorkDetail.getApsOrderId());
            Order order = orderMap.get(apsWorkDetail.getOrderId());

            int id = current.getId();
//            String path = PkgUtils.gen(apsOrder.getSeq()) + "→";
            String path = "";
            while (true) {
                Map<Integer, ApsWorkOrder> orderApsWorkOrderMap = allApsWorkOrderMap.get(order.getId());
                ApsWorkOrder pathCur = orderApsWorkOrderMap.get(id);
                if (ObjectUtils.isEmpty(pathCur) || pathCur.getPid() == null) {
//                    path = PkgUtils.gen(apsOrder.getSeq()) + path;
                    break;
                }
                ApsWorkOrder pathPar = orderApsWorkOrderMap.get(pathCur.getPid());
                path = "→" + pathPar.getPlmId() + path;
                id = pathPar.getId();
            }

            SinoCamPushDrawing pushDraw = sinoCamPushPushDrawMap.get(apsWorkDetail.getPlmId());

            pushPlan.setComponentId(parent.getPlmId());
            pushPlan.setComponentName(parent.getMaterName());
            pushPlan.setFactoryIdk(factoryMap.get(apsWorkDetail.getFactoryId()).getMyCode());
            pushPlan.setNeedDate(apsWorkDetail.getPlanStartDateTime());
            pushPlan.setNestPlanId(String.valueOf(apsWorkDetail.getId()));
            pushPlan.setPartId(current.getPlmId());
            pushPlan.setPartName(current.getMaterName());
            pushPlan.setPartType("1");
            pushPlan.setPlanAmount(apsWorkDetail.getTotalCount());
            pushPlan.setProcessingNo(PkgUtils.gen(apsOrder.getSeq()));
            pushPlan.setApsOrderId(apsWorkDetail.getApsOrderId());
            pushPlan.setProductId(StringUtils.hasText(order.getConstructNo()) ? order.getConstructNo() : order.getOrderCode());
            pushPlan.setVersionBrief("V1");
            if (ObjectUtils.isEmpty(pushDraw) || pushDraw.getStatus() == 5) {
                pushPlan.setStatus(5);
                pushPlan.setErrorMsg("推送图纸异常。");
                pushPlan.setUniMaterCode(current.getPlmId() + "#A.0");
                pushPlan.setReplaceTexture(null);
                pushPlan.setReplaceThickness(null);
            } else {
                pushPlan.setStatus(1);
                pushPlan.setErrorMsg(null);
                pushPlan.setUniMaterCode(current.getPlmId() + "#" + pushDraw.getDrawVersion());
                pushPlan.setReplaceTexture(pushDraw.getTexture());
                pushPlan.setReplaceThickness(pushDraw.getThickNess());
            }
            pushPlan.setPlanFinishAmount(new BigDecimal(0));
            pushPlan.setOrderId(order.getId());
            pushPlan.setVersionNum(1);
            pushPlan.setConsumeStatus(0);
            pushPlan.setPath(path);

            pushPlanList.add(pushPlan);

            if (pushPlanMap.get(pushPlan.getNestPlanId()) != null) {
                sinoCamPushPlanMapper.lambdaUpdate().eq(SinoCamPushPlan::getNestPlanId, pushPlan.getNestPlanId()).set(SinoCamPushPlan::getPath, pushPlan.getPath()).update();
                pushPlanList.remove(pushPlan);
            }

        }

        if (CollUtil.isEmpty(pushPlanList)) {
            return;
        }
        sinoCamPushPlanMapper.insertBatchSomeColumn(pushPlanList);

    }


    public Order conversionOrder(ImportErpOrder importErpOrder, ImportErpBom currentBom, ImportErpMater importErpMater, List<OrderExternalSyncErrorResVo> errorList) {
        Order order = new Order();
        order.setOrderCode(importErpOrder.getOrderCode());
        order.setConstructNo(importErpOrder.getOrderCode());
        order.setMaterCode(currentBom.getGraphNo());
        order.setMaterName(currentBom.getMaterialName());
        order.setOrderQty(NumberUtil.parseInt(importErpOrder.getQty()));
        order.setFinishQty(0);
        if (importErpOrder.getOrderCode().startsWith("J")) {
            order.setOrderType(4);
        } else {
            order.setOrderType(1);
        }

        order.setOrderStatus(1);
        order.setOrderDateTime(importErpOrder.getAssignDate());
        order.setDeliveryDateTime(importErpOrder.getDeliTime());
        order.setPlmId(importErpMater.getPlmId());

        Customer customer = customerMapper.selectById(3);
        if (customer == null) {
            throw SyExceptionUtils.e("没有找到该客户");
        }

        order.setCustomerId(3);
        order.setCustomerCode(customer.getMyCode());
        order.setCustomerName(customer.getName());
        order.setOrderPriority(1);
        order.setOrderWeight(1);

        if (order.getOrderType().equals(1)) {
            order.setSuffix(OrderUtils.partType(importErpMater.getPlmId(), currentBom.getMaterialName()));
        }

        return order;
    }


    public List<OrderPhase> conversionPhase(Order order, List<OrderBom> bomList, List<ImportErpWorkOrderDetail> workOrderDetailList, List<ImportErpMapping> importErpMappings, List<OrderExternalSyncErrorResVo> errorList) {

        List<Phase> phaseList = phaseMapper.lambdaQuery().list();
        Map<Integer, Phase> phaseIdMap = phaseList.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        List<PhaseJob> phaseJobList = phaseJobMapper.lambdaQuery().list();
        Map<Integer, PhaseJob> phaseJobIdMap = phaseJobList.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        List<PhaseJobRef> phaseJobRefList = phaseJobRefMapper.lambdaQuery().list();
        Map<String, List<PhaseJobRef>> phaseCodeRefJob = phaseJobRefList.stream().sorted(Comparator.comparing(PhaseJobRef::getSeq)).collect(Collectors.groupingBy(e -> phaseIdMap.get(e.getPhaseId()).getMyCode(), LinkedHashMap::new, Collectors.toList()));
        Map<String, List<PhaseJob>> phaseJobMap = new HashMap<>();
        for (String s : phaseCodeRefJob.keySet()) {
            phaseJobMap.put(s, new ArrayList<>());
            List<PhaseJobRef> phaseJobRefs = phaseCodeRefJob.get(s);
            if (CollUtil.isNotEmpty(phaseJobRefs)) {
                phaseJobMap.put(s, phaseJobRefs.stream()
                        .sorted(Comparator.comparing(PhaseJobRef::getSeq))
                        .map(e -> {
                            return phaseJobIdMap.get(e.getPhaseJobId());
                        })
                        .collect(Collectors.toList()));
            }
        }

        Map<String, Map<String, ImportErpMapping>> erpMesOpMappingMap = importErpMappings.stream().collect(Collectors.groupingBy(ImportErpMapping::getErpOpCode, Collectors.toMap(ImportErpMapping::getErpOp, Function.identity(), (e1, e2) -> e1)));

        Map<String, Map<String, List<ImportErpWorkOrderDetail>>> workOrderCodeMaterialCodeMap = workOrderDetailList.stream()
                .collect(
                        Collectors.groupingBy(
                                ImportErpWorkOrderDetail::getWorkOrderCode,
                                Collectors.groupingBy(
                                        ImportErpWorkOrderDetail::getMaterialCode
                                )
                        )
                );

        List<OrderPhase> orderPhaseList = new ArrayList<>();
        bomList.sort(Comparator.comparing(OrderBom::getPlmId));

        Map<Integer, OrderBom> orderBomMap = bomList.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        for (OrderBom bom : bomList) {

            Map<String, List<ImportErpWorkOrderDetail>> stringListMap = workOrderCodeMaterialCodeMap.get(bom.getWorkOrderCode());
            int phaseSeq = 1;

            if (bom.getMaterType() == null) {
                errorList.add(new OrderExternalSyncErrorResVo(2, "材质或规格为空", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
                continue;
            }

            if (CollUtil.isEmpty(stringListMap) && bom.getMaterType().equals("Assembly") && !StringUtils.hasText(bom.getWorkChain())) {
                bom.setWorkChain(WorkshopProp.WW_PHASE_CODE);
                orderBomMapper.updateById(bom);

                OrderPhase topPhase = PhaseUtils.getWeiwaiPhase(
                        order.getId(), bom.getId(), bom.getWorkChain(),
                        phaseSeq, bom.getPlmId(), bom.getMaterName()
                );
                phaseSeq++;
                orderPhaseMapper.insert(topPhase);
            }

            if (stringListMap == null) {
                continue;
            }

            List<ImportErpWorkOrderDetail> importErpWorkOrderDetails = stringListMap.get(bom.getBomCode());
            if (importErpWorkOrderDetails == null) {
                continue;
            }

            BigDecimal reduce = importErpWorkOrderDetails.stream().reduce(BigDecimal.ZERO, (a, b) -> a.add(new BigDecimal(b.getSdgs() == null ? "0" : b.getSdgs())), BigDecimal::add);
            if (!bom.getWorkChain().equals("WL") && reduce.compareTo(BigDecimal.ZERO) == 0) {

                bom.setMaterType("Component");
                bom.setWorkChain("WL");//外协件定值
                bom.setReadyType(2);
                orderBomMapper.updateById(bom);
                continue;
            }

            if (bom.getMaterType().equals("Platepart")) {
                OrderPhase llPhase = PhaseUtils.genLingliaoPhase(order.getId(), bom.getId(), bom.getWorkChain(), phaseSeq, bom.getPlmId(), bom.getMaterName());
                phaseSeq++;
                orderPhaseList.add(llPhase);
            }

            Map<String, Integer> phaseCount = new HashMap<>();
            importErpWorkOrderDetails.sort(Comparator.comparing(ImportErpWorkOrderDetail::getSeq));
            for (ImportErpWorkOrderDetail detail : importErpWorkOrderDetails) {
                OrderPhase phase = new OrderPhase();
                phase.setOrderId(order.getId());
                phase.setBomId(bom.getId());

                //工时取sdgs
                if (detail.getSdgs() != null) {
                    phase.setWorkTime(new BigDecimal(detail.getSdgs()).multiply(new BigDecimal(60)).setScale(0, RoundingMode.UP).intValue());
                } else {
                    phase.setWorkTime(0);
                }
                phase.setOriWorkTime(phase.getWorkTime());

                //detailEntity.setProdSn(z.getSn());
                phase.setWorkChain(bom.getWorkChain());
                phase.setMaterNo(bom.getPlmId());
                phase.setMaterName(detail.getMaterialName());
                phase.setOp(detail.getOp());
                phase.setOpCode(detail.getOpCode());
                if (!detail.getOpCode().trim().startsWith("170")) {
                    continue;
                }
                if (erpMesOpMappingMap.get(detail.getOpCode()) == null) {
                    errorList.add(new OrderExternalSyncErrorResVo(4, detail.getMaterialName() + detail.getMaterialCode() + "工作中心编码【" + detail.getOpCode() + "】,缺工序编码【" + detail.getOp() + "】,请先维护工作中心映射!", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
//                    throw SyExceptionUtils.e("根据ERP工作中心编码“" + detail.getOpCode().trim() + "”未能找到对应的MES工作中心映射关系，请先维护工作中心映射!");
                    continue;

                }
                ImportErpMapping importErpMapping = null;
                if (detail.getOpCode().startsWith("129")) {
                    importErpMapping = erpMesOpMappingMap.get("129002").get("Z206");
                } else {
                    importErpMapping = erpMesOpMappingMap.get(detail.getOpCode()).get(detail.getOp());
                }

                if (importErpMapping == null) {
                    errorList.add(new OrderExternalSyncErrorResVo(4, detail.getMaterialName() + detail.getMaterialCode() + "工作中心编码【" + detail.getOpCode() + "】,缺工序编码【" + detail.getOp() + "】,请先维护工作中心映射!", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
                    continue;
                }
                Integer count = phaseCount.compute(importErpMapping.getMesWorkPhase(), (k, v) -> v == null ? 0 : v + 1);
                String phaseCodeCount = importErpMapping.getMesWorkPhase();

                if (count > 0) {
                    phaseCodeCount = importErpMapping.getMesWorkPhase() + String.format("%02d", count);
                }
                phase.setPhaseCode(phaseCodeCount);
                phase.setPhaseSeq(phaseSeq++);
                phase.setPhaseName(importErpMapping.getApsPhaseName());
                phase.setWorkGroupNumber(importErpMapping.getMesWorkCenter());

                if (phase.getWorkTime().compareTo(0) > 0) {
                    // 工序任务处理
                    List<PhaseJob> job = phaseJobMap.get(phase.getPhaseCode());
                    if (CollUtil.isNotEmpty(job)) {
                        int jobTime = TaskTimeUtils.calcJobTime(phase, job);
                        phase.setOriWorkTime(phase.getWorkTime());
                        phase.setWorkTime(phase.getWorkTime() + jobTime);
                    }
                }

                orderPhaseList.add(phase);

                if (StringUtils.hasText(detail.getWiremodel()) && !detail.getWiremodel().trim().equals("null")) {
                    phase.getAttr().put("type", "wire");
                    phase.getAttr().put("wiremodel", detail.getWiremodel());
                    phase.getAttr().put("wirenumber", detail.getWirenumber());
                    phase.getAttr().put("wirequota", detail.getWirequota());
                }

                if (bom.getWorkChain().equals("WL") && (phase.getPhaseCode().equals("JG") || phase.getPhaseCode().equals("HG"))) {
                    errorList.add(new OrderExternalSyncErrorResVo(2, detail.getMaterialName() + detail.getMaterialCode() + "数据异常, 类型识别为WL，但是有切割工序", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
                }
            }

            if (bom.getPid() != null) {
                if (bom.getMaterType().equals("Platepart") || (bom.getMaterType().equals("Assembly") && !MkPartUtils.supportKjPhase(bom.getPlmId(), bom.getMaterName()))) {
                    OrderBom parentBom = orderBomMap.get(bom.getPid());
                    if (MkPartUtils.supportKjPhase(parentBom.getPlmId(), parentBom.getMaterName())) {

                        OrderPhase llPhase = PhaseUtils.genKujianPhase(order.getId(), bom.getId(), bom.getWorkChain(), phaseSeq, bom.getPlmId(), bom.getMaterName());
                        phaseSeq++;
                        orderPhaseList.add(llPhase);

                    }
                }
            }
        }

        return orderPhaseList;
    }


    public List<OrderAccessories> conversionAndSaveAccessories(Order order, List<OrderBom> orderBomList, List<OrderExternalSyncErrorResVo> errorList, ImportErpBom currentBom, List<OrderPhase> orderPhaseList) {

        List<ImportErpBom> importErpBoms = importErpBomMapper.treeAll(currentBom.getErpOrderId());

        Map<String, List<ImportErpBom>> pmCodeList = importErpBoms.stream().collect(Collectors.groupingBy(ImportErpBom::getPmCode));

        List<ImportErpBom> l = new ArrayList<>();

        List<ImportErpBom> temp = new ArrayList<>();
        temp.add(currentBom);
        currentBom.setIsTop(1);

        while (!temp.isEmpty()) {
            List<ImportErpBom> t = new ArrayList<>();
            for (ImportErpBom importErpBom : temp) {
                List<ImportErpBom> importErpBoms1 = pmCodeList.get(importErpBom.getMaterialCode());
                if (importErpBoms1 == null) {
                    continue;
                }
                for (ImportErpBom erpBom : importErpBoms1) {
                    erpBom.setIsTop(0);
                }
                t.addAll(importErpBoms1);
            }
            l.addAll(temp);
            temp = t;
        }

        Map<String, OrderBom> collect = orderBomList.stream().collect(Collectors.toMap(OrderBom::getErpCode, Function.identity(), (e1, e2) -> e1));

        Map<Integer, Map<String, OrderPhase>> phaseBomIdPhaseCodeMap = orderPhaseList.stream().filter(e -> e.getPhaseCode().equals("PT")).collect(Collectors.groupingBy(OrderPhase::getBomId, Collectors.toMap(OrderPhase::getPhaseCode, e -> e)));

        List<OrderAccessories> orderAccessoriesList = l.stream()
                .filter(e -> e.getMaterialCode().matches("^(010|020|050|060).+$"))
                .map(e -> {
                    OrderAccessories oa = new OrderAccessories();
                    oa.setOrderType(order.getOrderType());
                    oa.setOrderId(order.getId());
                    oa.setMaterCode(e.getMaterialCode());
                    oa.setMaterName(e.getMaterialName());
                    oa.setSpec(e.getGrade());
                    oa.setModel(e.getGraphNo());
                    oa.setMaterial(e.getMaterial());
                    oa.setPartCount(new BigDecimal(e.getReqQty()));
                    oa.setType(Integer.parseInt(e.getMaterialCode().substring(0, 2)));

                    OrderBom orderBom = collect.get(e.getPmCode());
                    if (orderBom == null) {
                        return oa;
                    }
                    oa.setBomId(orderBom.getId());

                    if (e.getMaterialCode().startsWith("050")) {
                        Map<String, OrderPhase> stringOrderPhaseMap = phaseBomIdPhaseCodeMap.get(oa.getBomId());
                        if (stringOrderPhaseMap == null) {
                            return oa;
                        }

                        OrderPhase orderPhase = stringOrderPhaseMap.get("PT");
                        oa.setPhaseId(orderPhase.getId());
                        oa.setPhaseCode(orderPhase.getPhaseCode());
                    }

                    return oa;
                })
                .collect(Collectors.toList());

        Map<Integer, Map<String, OrderAccessories>> collect1 = orderAccessoriesList.stream().filter(e -> e.getMaterCode().startsWith("020")).collect(Collectors.groupingBy(OrderAccessories::getBomId, Collectors.toMap(e -> e.getMaterCode(), e -> e)));

        Map<Integer, OrderBom> orderBomIdMap = orderBomList.stream().collect(Collectors.toMap(OrderBom::getId, Function.identity()));
        List<OrderAccessories> oaHansi = orderPhaseList.stream()
                .filter(e -> CollUtil.isNotEmpty(e.getAttr()) && e.getAttr().get("type").equals("wire"))
                .map(e -> {
                    OrderBom orderBom = orderBomIdMap.get(e.getBomId());
                    OrderAccessories oa = new OrderAccessories();
                    oa.setOrderType(order.getOrderType());
                    oa.setOrderId(order.getId());
                    oa.setBomId(orderBom.getId());
                    oa.setPhaseId(e.getId());
                    oa.setPhaseCode(e.getPhaseCode());
                    oa.setType(2);
                    oa.setMaterCode(e.getAttr().get("wirenumber"));
                    oa.setModel(e.getAttr().get("wiremodel"));
                    oa.setPartCount(new BigDecimal(e.getAttr().get("wirequota")));

                    Map<String, OrderAccessories> stringOrderAccessoriesMap = collect1.get(orderBom.getId());
                    if (stringOrderAccessoriesMap == null) {
                        return oa;
                    }

                    OrderAccessories accessories = stringOrderAccessoriesMap.get(oa.getMaterCode());
                    if (accessories == null) {
                        return oa;
                    }

                    oa.setMaterName(accessories.getMaterName());
                    oa.setSpec(accessories.getSpec());
                    oa.setMaterial(accessories.getMaterial());
                    return oa;

                })
                .collect(Collectors.toList());

        List<OrderAccessories> all = orderAccessoriesList.stream().filter(e -> !e.getMaterCode().startsWith("020")).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(oaHansi)) {
            all.addAll(oaHansi);
        }

        orderAccessoriesMapper.insertBatch(all);

        return orderAccessoriesList;
    }


    public void savePart(List<OrderBom> orderBomList, Order order, List<ImportErpMater> materList, List<ImportErpWorkOrder> erpWorkOrderList, List<ImportErpWorkOrderDetail> workOrderDetailList, List<ImportErpMapping> importErpMappings, List<OrderExternalSyncErrorResVo> errorList) {
        List<String> collect = orderBomList.stream().map(OrderBom::getPlmId).distinct().collect(Collectors.toList());
        List<OrderPart> hasPartList = orderPartMapper.lambdaQuery().in(OrderPart::getPlmId, collect).list();
        Map<String, OrderPart> hasPartMap = hasPartList.stream().collect(Collectors.toMap(OrderPart::getPlmId, Function.identity()));
        // 判断表中有没有，没有就全量写入，有就跳过该条
        List<OrderPart> orderParts = new ArrayList<>();
        for (OrderBom orderBom : orderBomList) {

            OrderPart orderPart = hasPartMap.get(orderBom.getPlmId());
            if (orderPart != null) {
                continue;
            }

            orderPart = new OrderPart();
            orderPart.setType(2); // 普通件
            orderPart.setNetWeight(orderBom.getMaterWeight());
            // orderPart.setArea(); // 面积
            orderPart.setWorkChain(orderBom.getWorkChain()); // 工序链
            orderPart.setSource(orderBom.getReadyType()); // 备料方式：1 自制  2 外购
            // orderPart.setCritical(); // 是否关键件 0不是 1是
            orderPart.setVersionCode(1L); // 版本号
            orderPart.setMaterType(orderBom.getMaterType()); // 物料类别
            orderPart.setPlmId(orderBom.getPlmId());
            // orderPart.setPngUrl(); // 零件PNG图纸路径
            // orderPart.setDxfUrl(); // 零件DXF图纸路径
            orderPart.setDrawing(orderBom.getDrawing());
            if (!Objects.equals(orderBom.getMaterType(), "Platepart")) {
                orderPart.setTexture(orderBom.getTexture());
            } else {
                String[] split = orderBom.getStandards().split("δ");
                if (orderBom.getTexture() != null) {
                    orderPart.setTexture(orderBom.getTexture());
                } else {
                    orderPart.setTexture(split[0]);
                }
                if (orderBom.getMaterHigh() != null) {
                    orderPart.setThickness(new BigDecimal(orderBom.getMaterHigh()));
                } else {
                    orderPart.setThickness(new BigDecimal(split[1]));
                }
            }
            // orderPart.setLength(); // 宽度
            // orderPart.setWidth(); // 长度


            String code = orderBom.getPlmId();
            if (code.endsWith("_170")) {
                code = code.substring(0, code.indexOf("_170"));
            }
            ImportMbdDxf importMbdDxf = importMbdDxfMapper.lambdaQuery().eq(ImportMbdDxf::getPlmid, code).orderByDesc(ImportMbdDxf::getDocVersion).last("limit 1").one();
            orderPart.setDrawStatus(1); // 是否制图就绪，默认 未就绪
            orderPart.setVersionNum(importMbdDxf != null ? importMbdDxf.getDocVersion() : null); // 图纸版本号
            orderPart.setDrawUpdateTime(null); // 图纸更新时间

            orderParts.add(orderPart);
            hasPartMap.put(orderPart.getPlmId(), orderPart);
        }
        if (!CollUtil.isEmpty(orderParts)) {
            orderPartMapper.insertBatchSomeColumn(orderParts);
        }

    }

    @Transactional
    public void orderErp(ImportFrameOrderPubReqVo reqVo) {

        List<OrderExternalSyncErrorResVo> errorList = new ArrayList<>();

        ImportErpBom currentBom = importErpBomMapper.selectById(reqVo.getId());
        if (currentBom == null) {
            throw SyExceptionUtils.e("没有找到该节点，请刷新后重试");
        }

        if ("R".equals(currentBom.getStatusId())) {
            throw SyExceptionUtils.e("该节点状态异常");
        }

        Integer count = importFrameBomMapper.lambdaQuery().eq(ImportFrameBom::getOrderId, reqVo.getTargetId()).count();
        if (count > 0) {
            throw SyExceptionUtils.e("该架型下有BOM数据，请先清空再导入");
        }

        ImportErpOrder importErpOrder = importErpOrderMapper.selectById(currentBom.getErpOrderId());

        // 获取所有的子节点
        List<ImportErpBom> allBomTree = findAllTree(importErpOrder);

        // 获取可用的的子节点
        List<ImportErpBom> bomChildren = findBomChildren(currentBom);

        List<String> materCodeList = bomChildren.stream().map(ImportErpBom::getMaterialCode).collect(Collectors.toList());

        // 获取所有的物料信息组成Map，供BOM使用
        List<ImportErpMater> materList = getMaterMap(currentBom.getErpOrderId(), materCodeList);

        // 获取所有的工单信息组成Map，供BOM使用
        List<ImportErpWorkOrder> erpWorkOrderList = getWorkOrderMap(currentBom.getErpOrderId(), materCodeList);

        // 获取所有的工单明细组成Map，供BOM使用
        List<ImportErpWorkOrderDetail> workOrderDetailList = getWorkOrderDetailMap(currentBom.getErpOrderId(), materCodeList);

        // 获取所有的工序映射，供BOM使用
        List<ImportErpMapping> importErpMappings = importErpMappingMapper.selectList(null);

        // 转换订单
        Optional<ImportErpMater> first = materList.stream().filter(e -> e.getMaterialCode().equals(currentBom.getMaterialCode())).findFirst();
        if (!first.isPresent()) {
            throw SyExceptionUtils.e("找不到对应的物料信息");
        }
        Order order = conversionOrderJiaxing(importErpOrder, currentBom, first.get(), errorList);

        ImportFrameOrder newOrder = importFrameOrderMapper.selectById(reqVo.getTargetId());

        // 保存订单
        saveOrder(order, newOrder, errorList);

        // 转换BOM
        List<OrderBom> orderBomList = conversionBom(order, newOrder, importErpOrder, allBomTree, bomChildren, materList, erpWorkOrderList, workOrderDetailList, importErpMappings, errorList);

        // 转换工序
        List<OrderPhase> orderPhaseList = conversionPhase(order, newOrder, orderBomList, workOrderDetailList, importErpMappings, errorList);
        savePhase(orderPhaseList);

        String key = "mom-srv-aps:order-sync:error:" + order.getConstructNo() + ":" + first.get().getPlmId();
        if (CollUtil.isNotEmpty(errorList)) {
            // 存redis
            stringRedisTemplate.opsForValue()
                    .set(key, JsonUtils.toJsonString(errorList), 10, TimeUnit.DAYS);

            throw SyExceptionUtils.e("同步失败，请查看Excel的错误信息");
        }
        stringRedisTemplate.delete(key);

    }

    public void saveOrder(Order order, ImportFrameOrder newOrder, List<OrderExternalSyncErrorResVo> errorList) {
        Integer extracted = getSerialNum(order.getConstructNo(), order.getOrderType());
        order.setSerialNum(extracted);
        order.setSerialCode(String.format("%04d-", order.getSerialNum()) + order.getConstructNo());

        Customer customer = customerMapper.selectById(3);
        if (customer == null) {
            throw SyExceptionUtils.e("没有找到该客户");
        }

        order.setCustomerId(3);
        order.setCustomerCode(customer.getMyCode());
        order.setCustomerName(customer.getName());
        order.setOrderPriority(1);
        order.setOrderWeight(1);

    }

    public void savePhase(List<OrderPhase> orderPhaseList) {
        if (CollUtil.isEmpty(orderPhaseList)) {
            return;
        }
        orderPhaseMapper.insertBatchSomeColumn(orderPhaseList);
    }

    public List<OrderPhase> conversionPhase(Order order, ImportFrameOrder newOrder, List<OrderBom> bomList, List<ImportErpWorkOrderDetail> workOrderDetailList, List<ImportErpMapping> importErpMappings, List<OrderExternalSyncErrorResVo> errorList) {

        List<Phase> phaseList = phaseMapper.lambdaQuery().list();
        Map<Integer, Phase> phaseIdMap = phaseList.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        List<PhaseJob> phaseJobList = phaseJobMapper.lambdaQuery().list();
        Map<Integer, PhaseJob> phaseJobIdMap = phaseJobList.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        List<PhaseJobRef> phaseJobRefList = phaseJobRefMapper.lambdaQuery().list();
        Map<String, List<PhaseJobRef>> phaseCodeRefJob = phaseJobRefList.stream().sorted(Comparator.comparing(PhaseJobRef::getSeq)).collect(Collectors.groupingBy(e -> phaseIdMap.get(e.getPhaseId()).getMyCode(), LinkedHashMap::new, Collectors.toList()));
        Map<String, List<PhaseJob>> phaseJobMap = new HashMap<>();
        for (String s : phaseCodeRefJob.keySet()) {
            phaseJobMap.put(s, new ArrayList<>());
            List<PhaseJobRef> phaseJobRefs = phaseCodeRefJob.get(s);
            if (CollUtil.isNotEmpty(phaseJobRefs)) {
                phaseJobMap.put(s, phaseJobRefs.stream()
                        .sorted(Comparator.comparing(PhaseJobRef::getSeq))
                        .map(e -> {
                            return phaseJobIdMap.get(e.getPhaseJobId());
                        })
                        .collect(Collectors.toList()));
            }
        }

        Map<String, Map<String, ImportErpMapping>> erpMesOpMappingMap = importErpMappings.stream().collect(Collectors.groupingBy(ImportErpMapping::getErpOpCode, Collectors.toMap(ImportErpMapping::getErpOp, Function.identity(), (e1, e2) -> e1)));

        Map<String, Map<String, List<ImportErpWorkOrderDetail>>> workOrderCodeMaterialCodeMap = workOrderDetailList.stream()
                .collect(
                        Collectors.groupingBy(
                                ImportErpWorkOrderDetail::getWorkOrderCode,
                                Collectors.groupingBy(
                                        ImportErpWorkOrderDetail::getMaterialCode
                                )
                        )
                );

        List<OrderPhase> orderPhaseList = new ArrayList<>();
        bomList.sort(Comparator.comparing(OrderBom::getPlmId));

        Map<Integer, OrderBom> orderBomMap = bomList.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        for (OrderBom bom : bomList) {

            Map<String, List<ImportErpWorkOrderDetail>> stringListMap = workOrderCodeMaterialCodeMap.get(bom.getWorkOrderCode());
            if (stringListMap == null) {
                continue;
            }

            List<ImportErpWorkOrderDetail> importErpWorkOrderDetails = stringListMap.get(bom.getBomCode());
            if (importErpWorkOrderDetails == null) {
                continue;
            }

            BigDecimal reduce = importErpWorkOrderDetails.stream().reduce(BigDecimal.ZERO, (a, b) -> a.add(new BigDecimal(b.getSdgs() == null ? "0" : b.getSdgs())), BigDecimal::add);
            if (!bom.getWorkChain().equals("WL") && reduce.compareTo(BigDecimal.ZERO) == 0) {

                bom.setMaterType("Component");
                bom.setWorkChain("WL");//外协件定值
                bom.setReadyType(2);
                orderBomMapper.updateById(bom);
                continue;
            }

            int phaseSeq = 1;

            if (bom.getMaterType().equals("Platepart")) {
                OrderPhase phase = new OrderPhase();
                phase.setOrderId(newOrder.getId());
                phase.setBomId(bom.getId());
                phase.setWorkTime(0);
                phase.setWorkChain(bom.getWorkChain());
                phase.setPhaseSeq(phaseSeq++);
                phase.setMaterNo(bom.getPlmId());
                phase.setMaterName(bom.getMaterName());
                phase.setPhaseCode(WorkshopProp.LL_PHASE_CODE);
                phase.setPhaseName(WorkshopProp.LL_PHASE_NAME);
                phase.setWorkGroupNumber(WorkshopProp.LL_GROUP);
                phase.setOriWorkTime(phase.getWorkTime());
                orderPhaseList.add(phase);
            }

            Map<String, Integer> phaseCount = new HashMap<>();
            importErpWorkOrderDetails.sort(Comparator.comparing(ImportErpWorkOrderDetail::getSeq));
            for (ImportErpWorkOrderDetail detail : importErpWorkOrderDetails) {
                OrderPhase phase = new OrderPhase();
                phase.setOrderId(newOrder.getId());
                phase.setBomId(bom.getId());

                //工时取sdgs
                if (detail.getSdgs() != null) {
                    phase.setWorkTime(new BigDecimal(detail.getSdgs()).multiply(new BigDecimal(60)).setScale(0, RoundingMode.UP).intValue());
                } else {
                    phase.setWorkTime(0);
                }
                phase.setOriWorkTime(phase.getWorkTime());

                //detailEntity.setProdSn(z.getSn());
                phase.setWorkChain(bom.getWorkChain());
                phase.setMaterNo(bom.getPlmId());
                phase.setMaterName(detail.getMaterialName());
                if (!detail.getOpCode().trim().startsWith("170")) {
                    continue;
                }
                if (erpMesOpMappingMap.get(detail.getOpCode()) == null) {
                    errorList.add(new OrderExternalSyncErrorResVo(4, detail.getMaterialName() + detail.getMaterialCode() + "工作中心编码【" + detail.getOpCode() + "】,缺工序编码【" + detail.getOp() + "】,请先维护工作中心映射!", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
//                    throw SyExceptionUtils.e("根据ERP工作中心编码“" + detail.getOpCode().trim() + "”未能找到对应的MES工作中心映射关系，请先维护工作中心映射!");
                    continue;

                }
                ImportErpMapping importErpMapping = null;
                if (detail.getOpCode().startsWith("129")) {
                    importErpMapping = erpMesOpMappingMap.get("129002").get("Z206");
                } else {
                    importErpMapping = erpMesOpMappingMap.get(detail.getOpCode()).get(detail.getOp());
                }

                if (importErpMapping == null) {
                    errorList.add(new OrderExternalSyncErrorResVo(4, detail.getMaterialName() + detail.getMaterialCode() + "工作中心编码【" + detail.getOpCode() + "】,缺工序编码【" + detail.getOp() + "】,请先维护工作中心映射!", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
                    continue;
                }
                Integer count = phaseCount.compute(importErpMapping.getMesWorkPhase(), (k, v) -> v == null ? 0 : v + 1);
                String phaseCodeCount = importErpMapping.getMesWorkPhase();

                if (count > 0) {
                    phaseCodeCount = importErpMapping.getMesWorkPhase() + String.format("%02d", count);
                }
                phase.setPhaseCode(phaseCodeCount);
                phase.setPhaseSeq(phaseSeq++);
                phase.setPhaseName(importErpMapping.getApsPhaseName());
                phase.setWorkGroupNumber(importErpMapping.getMesWorkCenter());

                if (phase.getWorkTime().compareTo(0) > 0) {
                    // 工序任务处理
                    List<PhaseJob> job = phaseJobMap.get(phase.getPhaseCode());
                    if (CollUtil.isNotEmpty(job)) {
                        int jobTime = TaskTimeUtils.calcJobTime(phase, job);
                        phase.setOriWorkTime(phase.getWorkTime());
                        phase.setWorkTime(phase.getWorkTime() + jobTime);

                    }
                }

//                phase.setOriWorkTime(new BigDecimal(phase.getWorkTime()).divide(new BigDecimal(60), 2, RoundingMode.UP));
                orderPhaseList.add(phase);

                if (bom.getWorkChain().equals("WL") && (phase.getPhaseCode().equals("JG") || phase.getPhaseCode().equals("HG"))) {
                    errorList.add(new OrderExternalSyncErrorResVo(2, detail.getMaterialName() + detail.getMaterialCode() + "数据异常, 类型识别为WL，但是有切割工序", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
                }
            }

            if (bom.getPid() != null) {
                if (bom.getMaterType().equals("Platepart") || (bom.getMaterType().equals("Assembly") && !MkPartUtils.supportKjPhase(bom.getPlmId(), bom.getMaterName()))) {
                    OrderBom parentBom = orderBomMap.get(bom.getPid());
                    if (MkPartUtils.supportKjPhase(parentBom.getPlmId(), parentBom.getMaterName())) {
                        OrderPhase phase = new OrderPhase();
                        phase.setOrderId(newOrder.getId());
                        phase.setBomId(bom.getId());
                        phase.setWorkTime(1);
                        phase.setOriWorkTime(phase.getWorkTime());
                        phase.setWorkChain(bom.getWorkChain());
                        phase.setPhaseSeq(phaseSeq++);
                        phase.setMaterNo(bom.getPlmId());
                        phase.setMaterName(bom.getMaterName());
                        phase.setPhaseCode(WorkshopProp.KJ_PHASE_CODE);
                        phase.setPhaseName(WorkshopProp.KJ_PHASE_NAME);
                        phase.setWorkGroupNumber(WorkshopProp.KJ_GROUP);
                        orderPhaseList.add(phase);
                    }
                }
            }
        }

        return orderPhaseList;
    }

    public List<ImportErpBom> findAllTree(ImportErpOrder order) {
        return importErpBomMapper.selectList(Wrappers.<ImportErpBom>query().eq("erp_order_id", order.getId()));
    }

    public List<ImportErpBom> findBomChildren(ImportErpBom currentBom) {

        List<ImportErpBom> importErpBoms = importErpBomMapper.tree(currentBom.getErpOrderId());

        Map<String, List<ImportErpBom>> pmCodeList = importErpBoms.stream().collect(Collectors.groupingBy(ImportErpBom::getPmCode));

        List<ImportErpBom> l = new ArrayList<>();

        List<ImportErpBom> temp = new ArrayList<>();
        temp.add(currentBom);
        currentBom.setIsTop(1);

        while (!temp.isEmpty()) {
            List<ImportErpBom> t = new ArrayList<>();
            for (ImportErpBom importErpBom : temp) {
                List<ImportErpBom> importErpBoms1 = pmCodeList.get(importErpBom.getMaterialCode());
                if (importErpBoms1 == null) {
                    continue;
                }
                for (ImportErpBom erpBom : importErpBoms1) {
                    erpBom.setIsTop(0);
                }
                t.addAll(importErpBoms1);
            }
            l.addAll(temp);
            temp = t;
        }
        return l;
    }


    public List<ImportErpMater> getMaterMap(Integer erpOrderId, List<String> materCodeList) {

        QueryWrapper<ImportErpMater> query = Wrappers.query();
        query.eq("erp_order_id", erpOrderId);
        return importErpMaterMapper.selectList(query);
    }

    public List<ImportErpWorkOrder> getWorkOrderMap(Integer erpOrderId, List<String> bomChildren) {
        LambdaQueryWrapper<ImportErpWorkOrder> query = Wrappers.lambdaQuery();
        query.in(ImportErpWorkOrder::getMaterialCode, bomChildren);
        query.eq(ImportErpWorkOrder::getErpOrderId, erpOrderId);
        return importErpWorkOrderMapper.selectList(query);
    }


    public List<ImportErpWorkOrderDetail> getWorkOrderDetailMap(Integer erpOrderId, List<String> materCodeList) {
        QueryWrapper<ImportErpWorkOrderDetail> query = Wrappers.query();
        query.in("material_code", materCodeList);
        query.eq("erp_order_id", erpOrderId);
        return importErpWorkOrderDetailMapper.selectList(query);
    }

    public Order conversionOrderJiaxing(ImportErpOrder importErpOrder, ImportErpBom currentBom, ImportErpMater importErpMater, List<OrderExternalSyncErrorResVo> errorList) {
        Order order = new Order();
        order.setOrderCode(importErpOrder.getOrderCode());
        order.setConstructNo(importErpOrder.getOrderCode());
        order.setMaterCode(currentBom.getGraphNo());
        order.setMaterName(currentBom.getMaterialName());
        order.setOrderQty(NumberUtil.parseInt(importErpOrder.getQty()));
        order.setFinishQty(0);
        if (importErpOrder.getOrderCode().startsWith("J")) {
            order.setOrderType(4);
        } else {
            order.setOrderType(1);
        }
        order.setOrderStatus(1);
        order.setOrderDateTime(importErpOrder.getAssignDate());
        order.setDeliveryDateTime(importErpOrder.getDeliTime());
        order.setPlmId(importErpMater.getPlmId());

        Customer customer = customerMapper.selectById(3);
        if (customer == null) {
            throw SyExceptionUtils.e("没有找到该客户");
        }

        order.setCustomerId(3);
        order.setCustomerCode(customer.getMyCode());
        order.setCustomerName(customer.getName());
        order.setOrderPriority(1);
        order.setOrderWeight(1);

        return order;
    }


    public OrderBom swap(Order order, ImportErpBom bom, Map<String, ImportErpMater> materCodeMap, Map<String, List<ImportErpWorkOrder>> workOrderCodeMap, Map<String, List<ImportErpWorkOrderDetail>> workOrderDetailMap, Map<String, List<ImportErpBom>> bomPmCodeMap, Map<String, Map<String, ImportErpMapping>> erpMesOpMapping, Map<String, ImportErpBom> parentBom, OrderBom parent, List<OrderExternalSyncErrorResVo> errorList) {

        OrderBom orderBom = new OrderBom();
        orderBom.setFactoryNo("170");
        orderBom.setOrderId(order.getId());
        orderBom.setPackCenter(bom.getPickCenter());
        orderBom.setMaterName(bom.getMaterialName());
        orderBom.setStandards(bom.getGrade());
        orderBom.setErpCode(bom.getMaterialCode());
        orderBom.setErpParentCode(bom.getPmCode());
        orderBom.setPartCount(NumberUtil.round(bom.getPerReqQty(), 0));
        orderBom.setTopFlag(bom.getIsTop());
        orderBom.setBomCode(bom.getMaterialCode());
        orderBom.setParentBomCode(bom.getPmCode());

        if (parent == null) {
            orderBom.setTotalCount(orderBom.getPartCount());
            orderBom.setLevel(1);
        } else {
            orderBom.setTotalCount(parent.getTotalCount().multiply(orderBom.getPartCount()));
            orderBom.setLevel(parent.getLevel() + 1);
        }

        ImportErpMater importErpMater = materCodeMap.get(bom.getMaterialCode());
        if (importErpMater == null) {
//            throw SyExceptionUtils.e("找不到对应的物料信息");
            orderBom.setMaterCode(bom.getGraphNo());
            if (StringUtils.hasText(orderBom.getMaterCode())) {
                orderBom.setMaterCode(orderBom.getMaterCode().replaceAll("/", "-"));
            }
            orderBom.setPlmId(orderBom.getMaterCode());
            orderBom.setDrawing(orderBom.getMaterCode());
            orderBom.setMaterType("Component");
            orderBom.setWorkChain("WL");//外协件定值
            orderBom.setReadyType(2);
            orderBom.setAssemblyPath(parent.getAssemblyPath() + "/" + orderBom.getMaterCode());
            orderBom.setPid(parent.getId());
//            errorList.add(new OrderExternalSyncErrorResVo(2, "找不到零件信息：" + bom.getMaterialCode(), order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterialCode(), bom.getMaterialName(), null,String.format("%s%s", bom.getMaterial(), bom.getGrade()), bom.getPerReqQty(), bom.getPmCode(), bom.getStatusId(), null));
            return orderBom;
        }

        orderBom.setMaterCode(importErpMater.getPaintCode());
        if (StringUtils.hasText(orderBom.getMaterCode())) {
            orderBom.setMaterCode(orderBom.getMaterCode().replaceAll("/", "-"));
        }


        orderBom.setPlmId(importErpMater.getPlmId());
        if (orderBom.getPlmId() == null) {
            orderBom.setPlmId("");
        }
        if (StringUtils.hasText(orderBom.getPlmId())) {
            orderBom.setPlmId(orderBom.getPlmId().replaceAll("/", "-"));
        }

        if (importErpMater.getNetWeight() != null) {
            orderBom.setMaterWeight(NumberUtil.round(importErpMater.getNetWeight(), 2));
        }

        orderBom.setDrawing(importErpMater.getPaintCode());
        if (StringUtils.hasText(orderBom.getDrawing())) {
            orderBom.setDrawing(orderBom.getDrawing().replaceAll("/", "-"));
        }


        List<ImportErpWorkOrder> workOrderList = workOrderCodeMap.get(bom.getMaterialCode());
        ImportErpWorkOrder workOrder = null;
        if (CollUtil.isNotEmpty(workOrderList)) {
            workOrder = findDueDate(workOrderList);
            if (workOrder != null) {
                orderBom.setDueDate(workOrder.getPlanEndTime());
            }
        }

        if (workOrder == null) {
            workOrder = new ImportErpWorkOrder();
            workOrder.setIsComponent("1");
            workOrder.setWorkOrderCode("WO-XXXXXXX");
            workOrder.setWorkOrderType("1");
//                    orderBom.setDueDate(bom.getMarkDate());// 代码有问题，ERP没这个字段，所有注释
        }


        List<ImportErpWorkOrderDetail> workOrderDetailList = workOrderDetailMap.get(bom.getMaterialCode());
        // 如果无工序明细，则为外协件
        if (workOrderDetailList == null) {
            orderBom.setMaterType("Component");
            orderBom.setWorkChain("WL");//外协件定值
            orderBom.setReadyType(workOrder.getIsComponent().equals("1") ? 2 : 1);
        }

        String spec = importErpMater.getSpec();//.replaceAll(REGEX_CHINESE, "");
        if (spec != null) {
            if (spec.contains("组件")) {
                orderBom.setMaterType("Assembly"); // 组件类型，Assembly
            } else if (workOrderDetailList == null) {
                //如果无工序明细，则为外协件
                orderBom.setMaterType("Component");
                orderBom.setWorkChain("WL");//外协件定值
                orderBom.setReadyType("1".equals(workOrder.getIsComponent()) ? 2 : 1);
            } else if (spec.contains("δ")) {
                orderBom.setMaterType("Platepart");//Platepart
                orderBom.setReadyType("1".equals(workOrder.getIsComponent()) ? 2 : 1);

                //施工单 物料号  获取 工单bom
                List<ImportErpBom> plateList = bomPmCodeMap.get(bom.getMaterialCode());
                if (plateList == null || plateList.isEmpty()) {
                    errorList.add(new OrderExternalSyncErrorResVo(2, "找不到对应的板材材质或规格信息", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterialCode(), bom.getMaterialName(), null, String.format("%s%s", bom.getMaterial(), bom.getGrade()), bom.getPerReqQty(), bom.getPmCode(), bom.getStatusId(), bom.getMaterialCode()));
                    return orderBom;
//                    throw SyExceptionUtils.e("找不到对应的板材材质或规格信息");
                } else {
                    ImportErpBom plateBom = plateList.get(0);
                    if (StringUtils.hasText(plateBom.getMaterial()) && StringUtils.hasText(plateBom.getGrade())) {
                        orderBom.setTexture(plateBom.getMaterial());//材质
                        String str = plateBom.getGrade().replace("δ", "");
                        try {
                            orderBom.setMaterHigh(NumberUtil.round(str, 0).intValue());//厚度

                        } catch (Exception e) {
                            e.printStackTrace();
                            throw e;
                        }
                    } else {
                        errorList.add(new OrderExternalSyncErrorResVo(2, "材质或规格为空", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterialCode(), bom.getMaterialName(), null, String.format("%s%s", bom.getMaterial(), bom.getGrade()), bom.getPerReqQty(), bom.getPmCode(), bom.getStatusId(), bom.getMaterialCode()));
                        return orderBom;
//                        throw SyExceptionUtils.e("材质或规格为空");
                    }


                }
            } else {
                orderBom.setMaterType("Component");
                orderBom.setWorkChain("WL");//外协件定值
                orderBom.setReadyType("1".equals(workOrder.getIsComponent()) ? 2 : 1);
            }
        }

        //工单类型0-自制；1-外协
        if (workOrder.getWorkOrderType().equals("1")) {
            orderBom.setMaterType("Component");
            orderBom.setWorkChain("WL");//外协件定值
            orderBom.setReadyType(workOrder.getIsComponent().equals("1") ? 2 : null);
        }

        if (orderBom.getMaterType() == null) {
            errorList.add(new OrderExternalSyncErrorResVo(2, "无法判断物料类型!", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterialCode(), bom.getMaterialName(), null, String.format("%s%s", bom.getMaterial(), bom.getGrade()), bom.getPerReqQty(), bom.getPmCode(), bom.getStatusId(), bom.getMaterialCode()));
            return orderBom;
//            throw SyExceptionUtils.e("无法判断物料类型!");
        }

//            orderBom.setParentMaterNo(orderBom.getDrawing());
        //获取工序链
        if (!orderBom.getMaterType().equals("Component")) {
            String workChain = getWorkChain(workOrderDetailList, erpMesOpMapping, workOrder.getWorkOrderCode(), orderBom, errorList);
            orderBom.setWorkChain(workChain);
        }


        //ERP工单号
        orderBom.setWorkOrderCode(workOrder.getWorkOrderCode());

        // MES需要的路径，如果没用请注释
        if (orderBom.getTopFlag().equals(1)) {
            StringBuilder sb = new StringBuilder();

            ImportErpBom currentParent = parentBom.get(orderBom.getBomCode());
            while (currentParent != null) {
                ImportErpMater importErpMater1 = materCodeMap.get(currentParent.getMaterialCode());
                if (importErpMater1 == null) {
                    errorList.add(new OrderExternalSyncErrorResVo(2, "没有找到路径!", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterialCode(), bom.getMaterialName(), null, String.format("%s%s", bom.getMaterial(), bom.getGrade()), bom.getPerReqQty(), bom.getPmCode(), bom.getStatusId(), bom.getMaterialCode()));
                    return orderBom;
//                    throw SyExceptionUtils.e("没有找到路径!");
                }
                sb.insert(0, importErpMater1.getPlmId()).insert(0, "/");
                currentParent = parentBom.get(currentParent.getPmCode());
            }

            orderBom.setAssemblyPath(sb.toString());
        } else {
            orderBom.setAssemblyPath(parent.getAssemblyPath() + "/" + orderBom.getMaterCode());
            orderBom.setPid(parent.getId());
        }

        orderBom.setReadyType(orderBom.getWorkChain().equals("WL") ? 2 : 1);

        return orderBom;
    }

    public List<OrderBom> conversionBom(Order order, ImportErpOrder importErpOrder, List<ImportErpBom> allBomTree, List<ImportErpBom> bomChildren, List<ImportErpMater> erpMaterList, List<ImportErpWorkOrder> erpWorkOrderList, List<ImportErpWorkOrderDetail> workOrderDetailListAll, List<ImportErpMapping> importErpMappings, List<OrderExternalSyncErrorResVo> errorList) {
        Map<String, Map<String, ImportErpMapping>> erpMesOpMapping = importErpMappings.stream().collect(Collectors.groupingBy(ImportErpMapping::getErpOpCode, Collectors.toMap(ImportErpMapping::getErpOp, Function.identity(), (e1, e2) -> e1)));
        Map<String, List<ImportErpBom>> bomPmCodeMap = allBomTree.stream().collect(Collectors.groupingBy(ImportErpBom::getPmCode));
        Map<String, ImportErpMater> materCodeMap = erpMaterList.stream().collect(Collectors.toMap(ImportErpMater::getMaterialCode, Function.identity(), (e1, e2) -> e1));
        Map<String, List<ImportErpWorkOrder>> workOrderCodeMap = erpWorkOrderList.stream().collect(Collectors.groupingBy(ImportErpWorkOrder::getMaterialCode));
        Map<String, List<ImportErpWorkOrderDetail>> workOrderDetailMap = workOrderDetailListAll.stream().collect(Collectors.groupingBy(ImportErpWorkOrderDetail::getMaterialCode));
        Map<String, ImportErpBom> parentBom = allBomTree.stream().collect(Collectors.toMap(ImportErpBom::getMaterialCode, Function.identity(), (e1, e2) -> e1));

        List<OrderBom> orderBomList = new ArrayList<>();

        Optional<ImportErpBom> firstOptional = bomChildren.stream().filter(e -> e.getIsTop() == 1).findFirst();
        if (!firstOptional.isPresent()) {
//            errorList.add(new OrderExternalSyncErrorResVo(1, "找不到根节点"));
//            errorList.add(new OrderExternalSyncErrorResVo(1, "找不到根节点：" + importErpOrder.getOrderCode(), importErpOrder.getOrderCode(), null, null, null, null,null, null, null, null, null));
            throw SyExceptionUtils.e("找不到BOM的根节点!");
        }
        ImportErpBom importErpBom = firstOptional.get();
        OrderBom top = swap(order, importErpBom, materCodeMap, workOrderCodeMap, workOrderDetailMap, bomPmCodeMap, erpMesOpMapping, parentBom, null, errorList);
        String pattern = ".+" + WorkshopProp.PH_PATTERN;
        if (order.getOrderType() == 1 && !order.getMaterCode().matches(pattern)) {
//            OrderBom o = orderBomMapper.lambdaQuery().eq(OrderBom::getMaterCode, order.getMaterCode()).eq(OrderBom::getOrderId, order.getId()).one();
//            if (o == null) {
//                OrderBom orderBom = new OrderBom();
//                orderBom.setFactoryNo("170");
//                orderBom.setOrderId(order.getId());
//                orderBom.setMaterName(order.getMaterName());
//                orderBom.setMaterCode(order.getMaterCode());
//
//                int div = Integer.parseInt(importErpOrder.getQty()) / order.getOrderQty();
//                if(Integer.parseInt(importErpOrder.getQty()) % order.getOrderQty() != 0){
//                    throw SyExceptionUtils.e("订单数量必须为整数倍!");
//                }
//
//                if(div < 1){
//                    throw SyExceptionUtils.e("当前数量必须大于等于订单数量!");
//                }
//
//                orderBom.setPartCount(new BigDecimal(div));
//                orderBom.setTotalCount(orderBom.getPartCount());
//                orderBom.setBomCode(order.getMaterCode());
//                orderBom.setPlmId(order.getMaterCode());
//                orderBom.setMaterType("Assembly");
//                orderBom.setLevel(1);
//                orderBom.setReadyType(1);
//                orderBom.setDrawing(orderBom.getDrawing());
//
//                StringBuilder sb = new StringBuilder();
//
//                ImportErpBom currentParent = parentBom.get(orderBom.getBomCode());
//                while (currentParent != null) {
//                    ImportErpMater importErpMater1 = materCodeMap.get(currentParent.getMaterialCode());
//                    if (importErpMater1 == null) {
//                        // throw SyExceptionUtils.e("没有找到路径!");
////                        errorList.add(new OrderExternalSyncErrorResVo(2, "找不到零件信息：" + currentParent.getMaterialCode()));
//                        errorList.add(new OrderExternalSyncErrorResVo(2, "找不到零件信息：" + currentParent.getMaterialCode(), importErpOrder.getOrderCode(), currentParent.getWorkOrderCode(), currentParent.getMaterialCode(), currentParent.getMaterialName(), null,String.format("%s%s", currentParent.getMaterial(), currentParent.getGrade()), currentParent.getPerReqQty(), currentParent.getPmCode(), currentParent.getStatusId(), null));
//                    } else {
//                        sb.insert(0, importErpMater1.getPlmId()).insert(0, "/");
//                    }
//                    currentParent = parentBom.get(currentParent.getPmCode());
//                }
//
//                orderBom.setAssemblyPath(sb.toString());
//                orderBom.setTopFlag(1);
//                orderBom.setWorkChain(WorkshopProp.WW_PHASE_CODE);
//                orderBomMapper.insert(orderBom);
//
//                OrderPhase topPhase = PhaseUtils.getWeiwaiPhase(
//                        order.getId(), orderBom.getId(), orderBom.getWorkChain(),
//                        1, orderBom.getMaterCode(), orderBom.getMaterName()
//                );
//                orderPhaseMapper.insert(topPhase);
//
//                o = orderBom;
//            }
            OrderBom o = orderBomMapper.lambdaQuery().eq(OrderBom::getOrderId, order.getId()).eq(OrderBom::getLevel, 1).one();
            orderBomList.add(o);
            top.setPid(o.getId());

            orderBomList.add(top);
            top.setLevel(2);
            top.setTopFlag(0);
            top.setAssemblyPath(o.getAssemblyPath() + "/" + top.getDrawing());
            if (!StringUtils.hasText(top.getWorkChain())) {
                top.setWorkChain(WorkshopProp.WW_PHASE_CODE);
            }
            orderBomMapper.insert(top);

            if (top.getWorkChain().equals(WorkshopProp.WW_PHASE_CODE)) {
//                OrderPhase llPhase =PhaseUtils.genKujianPhase(
//                        order.getId(), top.getId(), top.getWorkChain(),
//                        1, top.getMaterCode(), top.getMaterName()
//                );
//
//                orderPhaseMapper.insert(llPhase);

                OrderPhase topWwPhase = PhaseUtils.getWeiwaiPhase(
                        order.getId(), top.getId(), top.getWorkChain(),
                        1, top.getMaterCode(), top.getMaterName()
                );
                orderPhaseMapper.insert(topWwPhase);
            }

        } else {
            orderBomList.add(top);
            orderBomMapper.insert(top);
        }


        Map<String, List<ImportErpBom>> collect = bomChildren.stream().collect(Collectors.groupingBy(ImportErpBom::getPmCode));
        List<OrderBom> orderBoms = Lists.newArrayList(top);

        while (!orderBoms.isEmpty()) {
            List<OrderBom> temp = Lists.newArrayList();
            for (OrderBom orderBom : orderBoms) {

                List<ImportErpBom> orderBoms1 = collect.get(orderBom.getBomCode());
                if (orderBoms1 == null) {
                    continue;
                }

                Map<String, OrderBom> map = new HashMap<>();
                for (ImportErpBom bom : orderBoms1) {
                    OrderBom swap = swap(order, bom, materCodeMap, workOrderCodeMap, workOrderDetailMap, bomPmCodeMap, erpMesOpMapping, parentBom, orderBom, errorList);
//                    if(orderBom.getWorkChain().equals("WL") && swap.getWorkChain().equals("WL")){
//                        continue;
//                    }

                    OrderBom bomHas = map.get(swap.getPlmId());
                    if (bomHas != null) {
                        continue;
                    }
                    map.put(swap.getPlmId(), swap);

                    temp.add(swap);
                    orderBomList.add(swap);
                    orderBomMapper.insert(swap);
                }
            }
            orderBoms = temp;

        }

        orderBomList.sort(Comparator.comparing(OrderBom::getBomCode));
        return orderBomList;


    }


    public List<OrderBom> conversionBom(Order order, ImportFrameOrder newOrder, ImportErpOrder importErpOrder, List<ImportErpBom> allBomTree, List<ImportErpBom> bomChildren, List<ImportErpMater> erpMaterList, List<ImportErpWorkOrder> erpWorkOrderList, List<ImportErpWorkOrderDetail> workOrderDetailListAll, List<ImportErpMapping> importErpMappings, List<OrderExternalSyncErrorResVo> errorList) {
        Map<String, Map<String, ImportErpMapping>> erpMesOpMapping = importErpMappings.stream().collect(Collectors.groupingBy(ImportErpMapping::getErpOpCode, Collectors.toMap(ImportErpMapping::getErpOp, Function.identity(), (e1, e2) -> e1)));
        Map<String, List<ImportErpBom>> bomPmCodeMap = allBomTree.stream().collect(Collectors.groupingBy(ImportErpBom::getPmCode));
        Map<String, ImportErpMater> materCodeMap = erpMaterList.stream().collect(Collectors.toMap(ImportErpMater::getMaterialCode, Function.identity(), (e1, e2) -> e1));
        Map<String, List<ImportErpWorkOrder>> workOrderCodeMap = erpWorkOrderList.stream().collect(Collectors.groupingBy(ImportErpWorkOrder::getMaterialCode));
        Map<String, List<ImportErpWorkOrderDetail>> workOrderDetailMap = workOrderDetailListAll.stream().collect(Collectors.groupingBy(ImportErpWorkOrderDetail::getMaterialCode));
        Map<String, ImportErpBom> parentBom = allBomTree.stream().collect(Collectors.toMap(ImportErpBom::getMaterialCode, Function.identity(), (e1, e2) -> e1));

        List<OrderBom> orderBomList = new ArrayList<>();

        Optional<ImportErpBom> firstOptional = bomChildren.stream().filter(e -> e.getIsTop() == 1).findFirst();
        if (!firstOptional.isPresent()) {
//            errorList.add(new OrderExternalSyncErrorResVo(1, "找不到根节点"));
//            errorList.add(new OrderExternalSyncErrorResVo(1, "找不到根节点：" + importErpOrder.getOrderCode(), importErpOrder.getOrderCode(), null, null, null, null,null, null, null, null, null));
            throw SyExceptionUtils.e("找不到BOM的根节点!");
        }
        ImportErpBom importErpBom = firstOptional.get();
        OrderBom top = swap(order, newOrder, importErpBom, materCodeMap, workOrderCodeMap, workOrderDetailMap, bomPmCodeMap, erpMesOpMapping, parentBom, null, errorList);
        String pattern = ".+" + WorkshopProp.PH_PATTERN;
        if (order.getOrderType() == 1 && !order.getMaterCode().matches(pattern)) {
            OrderBom o = orderBomMapper.lambdaQuery().eq(OrderBom::getMaterCode, order.getMaterCode()).eq(OrderBom::getOrderId, order.getId()).one();
            if (o == null) {
                OrderBom orderBom = new OrderBom();
                orderBom.setFactoryNo("170");
                orderBom.setOrderId(newOrder.getId());
                orderBom.setMaterName(order.getMaterName());
                orderBom.setMaterCode(order.getMaterCode());

                int div = Integer.parseInt(importErpOrder.getQty()) / order.getOrderQty();
                if (Integer.parseInt(importErpOrder.getQty()) % order.getOrderQty() != 0) {
                    throw SyExceptionUtils.e("订单数量必须为整数倍!");
                }

                if (div < 1) {
                    throw SyExceptionUtils.e("当前数量必须大于等于订单数量!");
                }

                orderBom.setPartCount(new BigDecimal(div));
                orderBom.setTotalCount(orderBom.getPartCount());
                orderBom.setBomCode(order.getMaterCode());
                orderBom.setPlmId(order.getMaterCode());
                orderBom.setMaterType("Assembly");
                orderBom.setLevel(1);
                orderBom.setReadyType(1);
                orderBom.setDrawing(orderBom.getDrawing());

                StringBuilder sb = new StringBuilder();

                ImportErpBom currentParent = parentBom.get(orderBom.getBomCode());
                while (currentParent != null) {
                    ImportErpMater importErpMater1 = materCodeMap.get(currentParent.getMaterialCode());
                    if (importErpMater1 == null) {
                        // throw SyExceptionUtils.e("没有找到路径!");
//                        errorList.add(new OrderExternalSyncErrorResVo(2, "找不到零件信息：" + currentParent.getMaterialCode()));
                        errorList.add(new OrderExternalSyncErrorResVo(2, "找不到零件信息：" + currentParent.getMaterialCode(), importErpOrder.getOrderCode(), currentParent.getWorkOrderCode(), currentParent.getMaterialCode(), currentParent.getMaterialName(), null, String.format("%s%s", currentParent.getMaterial(), currentParent.getGrade()), currentParent.getPerReqQty(), currentParent.getPmCode(), currentParent.getStatusId(), null));
                    }
                    sb.insert(0, importErpMater1.getPlmId()).insert(0, "/");
                    currentParent = parentBom.get(currentParent.getPmCode());
                }

                orderBom.setAssemblyPath(sb.toString());
                orderBom.setTopFlag(1);
                orderBom.setWorkChain("WW");
                orderBomMapper.insert(orderBom);

                OrderPhase topPhase = new OrderPhase();
                topPhase.setOrderId(newOrder.getId());
                topPhase.setBomId(orderBom.getId());
                topPhase.setWorkTime(1);
                topPhase.setOriWorkTime(1);
                topPhase.setPhaseSeq(1);
                topPhase.setPhaseCode("WW");
                topPhase.setPhaseName("委外");
                topPhase.setWorkGroupNumber("WW");
                topPhase.setMaterNo(orderBom.getMaterCode());
                topPhase.setMaterName(orderBom.getMaterName());
                topPhase.setWorkChain(orderBom.getWorkChain());
                orderPhaseMapper.insert(topPhase);

                o = orderBom;
            }
            orderBomList.add(o);
            top.setPid(o.getId());

            orderBomList.add(top);
            top.setLevel(2);
            top.setTopFlag(0);
            top.setAssemblyPath(o.getAssemblyPath() + "/" + top.getDrawing());
            if (!StringUtils.hasText(top.getWorkChain())) {
                top.setWorkChain("WW");
            }
            orderBomMapper.insert(top);

            if (top.getWorkChain().equals("WW")) {
                OrderPhase llPhase = new OrderPhase();
                llPhase.setOrderId(newOrder.getId());
                llPhase.setBomId(top.getId());
                llPhase.setWorkTime(1);
                llPhase.setOriWorkTime(llPhase.getWorkTime());
                llPhase.setWorkChain(top.getWorkChain());
                llPhase.setPhaseSeq(1);
                llPhase.setMaterNo(top.getMaterCode());
                llPhase.setMaterName(top.getMaterName());
                llPhase.setPhaseCode(WorkshopProp.KJ_PHASE_CODE);
                llPhase.setPhaseName(WorkshopProp.KJ_PHASE_NAME);
                llPhase.setWorkGroupNumber(WorkshopProp.KJ_GROUP);
                llPhase.setWorkChain(top.getWorkChain());
                orderPhaseMapper.insert(llPhase);

                OrderPhase topPhase = new OrderPhase();
                topPhase.setOrderId(newOrder.getId());
                topPhase.setBomId(top.getId());
                topPhase.setWorkTime(1);
                topPhase.setOriWorkTime(topPhase.getWorkTime());
                topPhase.setPhaseSeq(2);
                topPhase.setPhaseCode("WW");
                topPhase.setPhaseName("委外");
                topPhase.setWorkGroupNumber("WW");
                topPhase.setMaterNo(top.getMaterCode());
                topPhase.setMaterName(top.getMaterName());
                topPhase.setWorkChain(top.getWorkChain());
                orderPhaseMapper.insert(topPhase);
            }

        } else {
            orderBomList.add(top);
            orderBomMapper.insert(top);
        }


        Map<String, List<ImportErpBom>> collect = bomChildren.stream().collect(Collectors.groupingBy(ImportErpBom::getPmCode));
        List<OrderBom> orderBoms = Lists.newArrayList(top);

        while (!orderBoms.isEmpty()) {
            List<OrderBom> temp = Lists.newArrayList();
            for (OrderBom orderBom : orderBoms) {

                List<ImportErpBom> orderBoms1 = collect.get(orderBom.getBomCode());
                if (orderBoms1 == null) {
                    continue;
                }

                Map<String, OrderBom> map = new HashMap<>();
                for (ImportErpBom bom : orderBoms1) {
                    OrderBom swap = swap(order, newOrder, bom, materCodeMap, workOrderCodeMap, workOrderDetailMap, bomPmCodeMap, erpMesOpMapping, parentBom, orderBom, errorList);
//                    if(orderBom.getWorkChain().equals("WL") && swap.getWorkChain().equals("WL")){
//                        continue;
//                    }

                    OrderBom bomHas = map.get(swap.getPlmId());
                    if (bomHas != null) {
                        continue;
                    }
                    map.put(swap.getPlmId(), swap);

                    temp.add(swap);
                    orderBomList.add(swap);
                    orderBomMapper.insert(swap);
                }
            }
            orderBoms = temp;

        }

        orderBomList.sort(Comparator.comparing(OrderBom::getBomCode));
        return orderBomList;


    }

    public OrderBom swap(Order order, ImportFrameOrder newOrder, ImportErpBom bom, Map<String, ImportErpMater> materCodeMap, Map<String, List<ImportErpWorkOrder>> workOrderCodeMap, Map<String, List<ImportErpWorkOrderDetail>> workOrderDetailMap, Map<String, List<ImportErpBom>> bomPmCodeMap, Map<String, Map<String, ImportErpMapping>> erpMesOpMapping, Map<String, ImportErpBom> parentBom, OrderBom parent, List<OrderExternalSyncErrorResVo> errorList) {

        OrderBom orderBom = new OrderBom();
        orderBom.setFactoryNo("170");
        orderBom.setOrderId(newOrder.getId());
        orderBom.setPackCenter(bom.getPickCenter());
        orderBom.setMaterName(bom.getMaterialName());
        orderBom.setStandards(bom.getGrade());
        orderBom.setErpCode(bom.getMaterialCode());
        orderBom.setErpParentCode(bom.getPmCode());
        orderBom.setPartCount(NumberUtil.round(bom.getPerReqQty(), 0));
        orderBom.setTopFlag(bom.getIsTop());
        orderBom.setBomCode(bom.getMaterialCode());
        orderBom.setParentBomCode(bom.getPmCode());
        if (parent == null) {
            orderBom.setTotalCount(orderBom.getPartCount());
            orderBom.setLevel(1);
        } else {
            orderBom.setTotalCount(parent.getTotalCount().multiply(orderBom.getPartCount()));
            orderBom.setLevel(parent.getLevel() + 1);
        }

        ImportErpMater importErpMater = materCodeMap.get(bom.getMaterialCode());
        if (importErpMater == null) {
//            throw SyExceptionUtils.e("找不到对应的物料信息");
            orderBom.setMaterCode(bom.getGraphNo());
            if (StringUtils.hasText(orderBom.getMaterCode())) {
                orderBom.setMaterCode(orderBom.getMaterCode().replaceAll("/", "-"));
            }
            orderBom.setPlmId(orderBom.getMaterCode());
            orderBom.setDrawing(orderBom.getMaterCode());
            orderBom.setMaterType("Component");
            orderBom.setWorkChain("WL");//外协件定值
            orderBom.setReadyType(2);
            orderBom.setAssemblyPath(parent.getAssemblyPath() + "/" + orderBom.getMaterCode());
            orderBom.setPid(parent.getId());
//            errorList.add(new OrderExternalSyncErrorResVo(2, "找不到零件信息：" + bom.getMaterialCode(), order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterialCode(), bom.getMaterialName(), null,String.format("%s%s", bom.getMaterial(), bom.getGrade()), bom.getPerReqQty(), bom.getPmCode(), bom.getStatusId(), null));
            return orderBom;
        }

        orderBom.setMaterCode(importErpMater.getPaintCode());
        if (StringUtils.hasText(orderBom.getMaterCode())) {
            orderBom.setMaterCode(orderBom.getMaterCode().replaceAll("/", "-"));
        }


        orderBom.setPlmId(importErpMater.getPlmId());
        if (orderBom.getPlmId() == null) {
            orderBom.setPlmId("");
        }
        if (StringUtils.hasText(orderBom.getPlmId())) {
            orderBom.setPlmId(orderBom.getPlmId().replaceAll("/", "-"));
        }

        if (importErpMater.getNetWeight() != null) {
            orderBom.setMaterWeight(NumberUtil.round(importErpMater.getNetWeight(), 2));
        }

        orderBom.setDrawing(importErpMater.getPaintCode());
        if (StringUtils.hasText(orderBom.getDrawing())) {
            orderBom.setDrawing(orderBom.getDrawing().replaceAll("/", "-"));
        }


        List<ImportErpWorkOrder> workOrderList = workOrderCodeMap.get(bom.getMaterialCode());
        ImportErpWorkOrder workOrder = null;
        if (CollUtil.isNotEmpty(workOrderList)) {
            workOrder = findDueDate(workOrderList);
            if (workOrder != null) {
                orderBom.setDueDate(workOrder.getPlanEndTime());
            }
        }

        if (workOrder == null) {
            workOrder = new ImportErpWorkOrder();
            workOrder.setIsComponent("1");
            workOrder.setWorkOrderCode("WO-XXXXXXX");
            workOrder.setWorkOrderType("1");
//                    orderBom.setDueDate(bom.getMarkDate());// 代码有问题，ERP没这个字段，所有注释
        }


        List<ImportErpWorkOrderDetail> workOrderDetailList = workOrderDetailMap.get(bom.getMaterialCode());
        // 如果无工序明细，则为外协件
        if (workOrderDetailList == null) {
            orderBom.setMaterType("Component");
            orderBom.setWorkChain("WL");//外协件定值
            orderBom.setReadyType(workOrder.getIsComponent().equals("1") ? 2 : 1);
        }

        String spec = importErpMater.getSpec();//.replaceAll(REGEX_CHINESE, "");
        if (spec != null) {
            if (spec.contains("组件")) {
                orderBom.setMaterType("Assembly"); // 组件类型，Assembly
            } else if (workOrderDetailList == null) {
                //如果无工序明细，则为外协件
                orderBom.setMaterType("Component");
                orderBom.setWorkChain("WL");//外协件定值
                orderBom.setReadyType("1".equals(workOrder.getIsComponent()) ? 2 : 1);
            } else if (spec.contains("δ")) {
                orderBom.setMaterType("Platepart");//Platepart
                orderBom.setReadyType("1".equals(workOrder.getIsComponent()) ? 2 : 1);

                //施工单 物料号  获取 工单bom
                List<ImportErpBom> plateList = bomPmCodeMap.get(bom.getMaterialCode());
                if (plateList == null || plateList.isEmpty()) {
                    errorList.add(new OrderExternalSyncErrorResVo(2, "找不到对应的板材材质或规格信息", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterialCode(), bom.getMaterialName(), null, String.format("%s%s", bom.getMaterial(), bom.getGrade()), bom.getPerReqQty(), bom.getPmCode(), bom.getStatusId(), bom.getMaterialCode()));
                    return orderBom;
//                    throw SyExceptionUtils.e("找不到对应的板材材质或规格信息");
                } else {
                    ImportErpBom plateBom = plateList.get(0);
                    if (StringUtils.hasText(plateBom.getMaterial()) && StringUtils.hasText(plateBom.getGrade())) {
                        orderBom.setTexture(plateBom.getMaterial());//材质
                        String str = plateBom.getGrade().replace("δ", "");
                        try {
                            orderBom.setMaterHigh(NumberUtil.round(str, 0).intValue());//厚度

                        } catch (Exception e) {
                            e.printStackTrace();
                            throw e;
                        }
                    } else {
                        errorList.add(new OrderExternalSyncErrorResVo(2, "材质或规格为空", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterialCode(), bom.getMaterialName(), null, String.format("%s%s", bom.getMaterial(), bom.getGrade()), bom.getPerReqQty(), bom.getPmCode(), bom.getStatusId(), bom.getMaterialCode()));
                        return orderBom;
//                        throw SyExceptionUtils.e("材质或规格为空");
                    }


                }
            } else {
                orderBom.setMaterType("Component");
                orderBom.setWorkChain("WL");//外协件定值
                orderBom.setReadyType("1".equals(workOrder.getIsComponent()) ? 2 : 1);
            }
        }

        //工单类型0-自制；1-外协
        if (workOrder.getWorkOrderType().equals("1")) {
            orderBom.setMaterType("Component");
            orderBom.setWorkChain("WL");//外协件定值
            orderBom.setReadyType(workOrder.getIsComponent().equals("1") ? 2 : null);
        }

        if (orderBom.getMaterType() == null) {
            errorList.add(new OrderExternalSyncErrorResVo(2, "无法判断物料类型!", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterialCode(), bom.getMaterialName(), null, String.format("%s%s", bom.getMaterial(), bom.getGrade()), bom.getPerReqQty(), bom.getPmCode(), bom.getStatusId(), bom.getMaterialCode()));
            return orderBom;
//            throw SyExceptionUtils.e("无法判断物料类型!");
        }

//            orderBom.setParentMaterNo(orderBom.getDrawing());
        //获取工序链
        if (!orderBom.getMaterType().equals("Component")) {
            String workChain = getWorkChain(workOrderDetailList, erpMesOpMapping, workOrder.getWorkOrderCode(), orderBom, errorList);
            orderBom.setWorkChain(workChain);
        }


        //ERP工单号
        orderBom.setWorkOrderCode(workOrder.getWorkOrderCode());

        // MES需要的路径，如果没用请注释
        if (orderBom.getTopFlag().equals(1)) {
            StringBuilder sb = new StringBuilder();

            ImportErpBom currentParent = parentBom.get(orderBom.getBomCode());
            while (currentParent != null) {
                ImportErpMater importErpMater1 = materCodeMap.get(currentParent.getMaterialCode());
                if (importErpMater1 == null) {
                    errorList.add(new OrderExternalSyncErrorResVo(2, "没有找到路径!", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterialCode(), bom.getMaterialName(), null, String.format("%s%s", bom.getMaterial(), bom.getGrade()), bom.getPerReqQty(), bom.getPmCode(), bom.getStatusId(), bom.getMaterialCode()));
                    return orderBom;
//                    throw SyExceptionUtils.e("没有找到路径!");
                }
                sb.insert(0, importErpMater1.getPlmId()).insert(0, "/");
                currentParent = parentBom.get(currentParent.getPmCode());
            }

            orderBom.setAssemblyPath(sb.toString());
        } else {
            orderBom.setAssemblyPath(parent.getAssemblyPath() + "/" + orderBom.getMaterCode());
            orderBom.setPid(parent.getId());
        }

        orderBom.setReadyType(orderBom.getWorkChain().equals("WL") ? 2 : 1);

        return orderBom;
    }

    public String getWorkChain(List<ImportErpWorkOrderDetail> allWorkOrderDetailList, Map<String, Map<String, ImportErpMapping>> erpMesOpMappingMap, String workOrderCode, OrderBom bom, List<OrderExternalSyncErrorResVo> errorList) {
        String workChain = "";
        if (CollUtil.isEmpty(allWorkOrderDetailList)) {
            return workChain;
        }

        List<ImportErpWorkOrderDetail> detailList = allWorkOrderDetailList
                .stream()
                .filter(e -> !"70020604".equals(e.getOpCode()))
                .filter(e -> !"Z105".equals(e.getOp()))
                .filter(e -> workOrderCode.equals(e.getWorkOrderCode()))
                .sorted(Comparator.comparing(ImportErpWorkOrderDetail::getSeq))
                .collect(Collectors.toList());

        if (CollUtil.isEmpty(detailList)) {
            return workChain;
        }

        Map<String, Integer> phaseCount = new HashMap<>();
        for (ImportErpWorkOrderDetail detail : detailList) {

            if (!StringUtils.hasText(detail.getOpCode())) {
//                throw SyExceptionUtils.e("根据ERP工作中心编码“" + detail.getOpCode() + "”,ERP工序编码“" + detail.getOp() + "”,物料编码“" + detail.getMaterialCode() + "”未能找到对应的MES工作中心映射关系，请先维护工作中心映射!");
//                errorList.add("根据ERP工作中心编码“" + detail.getOpCode() + "”,ERP工序编码“" + detail.getOp() + "”,物料编码“" + detail.getMaterialCode() + "”未能找到对应的MES工作中心映射关系，请先维护工作中心映射!");
                errorList.add(new OrderExternalSyncErrorResVo(4, detail.getMaterialName() + detail.getMaterialCode() + "工作中心编码【" + detail.getOpCode() + "】,缺工序编码【" + detail.getOp() + "】,请先维护工作中心映射!", null, bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
                return workChain;
            }

            if (!detail.getOpCode().trim().startsWith("170")) {
                continue;
            }

            if (!StringUtils.hasText(detail.getOp())) {
//                throw SyExceptionUtils.e("根据ERP工作中心编码“" + detail.getOpCode() + "”,ERP工序编码“" + detail.getOp() + "”,物料编码“" + detail.getMaterialCode() + "”未能找到对应的MES工作中心映射关系，请先维护工作中心映射!");
//                errorList.add("根据ERP工作中心编码“" + detail.getOpCode() + "”,ERP工序编码“" + detail.getOp() + "”,物料编码“" + detail.getMaterialCode() + "”未能找到对应的MES工作中心映射关系，请先维护工作中心映射!");
                errorList.add(new OrderExternalSyncErrorResVo(4, detail.getMaterialName() + detail.getMaterialCode() + "工作中心编码【" + detail.getOpCode() + "】,缺工序编码【" + detail.getOp() + "】,请先维护工作中心映射!", null, bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
                return workChain;
            }

            if (detail.getOpCode().startsWith("129")) {
                workChain += "ZP-";//如果工作中心以129开头，直接截断后续所有工序，增加ZP工序
                break;
            }

            if (erpMesOpMappingMap.get(detail.getOpCode()) == null) {
//                throw SyExceptionUtils.e("根据ERP工作中心编码“" + detail.getOpCode() + "”,ERP工序编码“" + detail.getOp() + "”,物料编码“" + detail.getMaterialCode() + "”未能找到对应的MES工作中心映射关系，请先维护工作中心映射!");
                errorList.add(new OrderExternalSyncErrorResVo(4, detail.getMaterialName() + detail.getMaterialCode() + "工作中心编码【" + detail.getOpCode() + "】,缺工序编码【" + detail.getOp() + "】,请先维护工作中心映射!", null, bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
                return workChain;
            }
            ImportErpMapping importErpMapping = erpMesOpMappingMap.get(detail.getOpCode()).get(detail.getOp());

            if (importErpMapping == null) {
                errorList.add(new OrderExternalSyncErrorResVo(4, detail.getMaterialName() + detail.getMaterialCode() + "工作中心编码【" + detail.getOpCode() + "】,缺工序编码【" + detail.getOp() + "】,请先维护工作中心映射!", null, bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
//                throw SyExceptionUtils.e("根据ERP工作中心编码“" + detail.getOpCode() + "”,ERP工序编码“" + detail.getOp() + "”,物料编码“" + detail.getMaterialCode() + "”未能找到对应的MES工作中心映射关系，请先维护工作中心映射!");
            } else {
                String str = importErpMapping.getMesWorkPhase();
                Integer count = phaseCount.compute(str, (k, v) -> v == null ? 0 : v + 1);
                String phaseCodeCount = str + "-";
                if (count > 0) {
                    phaseCodeCount = str + String.format("%02d", count) + "-";
                }
                workChain += phaseCodeCount;
            }
        }
        if (org.apache.commons.lang.StringUtils.isNotBlank(workChain)) {
            workChain = workChain.substring(0, workChain.length() - 1);
        } else {
//            throw SyExceptionUtils.e("工序链生成失败！");
            errorList.add(new OrderExternalSyncErrorResVo(4, "工序链生成失败!", null, bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
        }


        return workChain;
    }

    public ImportErpWorkOrder findDueDate(List<ImportErpWorkOrder> infoList) {
        if (infoList.size() == 1) {
            return infoList.get(0);

        }

        //过滤掉 3 和4  已取消的
        List<ImportErpWorkOrder> collectList = infoList
                .stream()
                .filter(s -> !s.getWorkOrderState().equals("3") && !s.getWorkOrderState().equals("4"))
                .collect(Collectors.toList());
        if (CollUtil.isNotEmpty(collectList)) {
            return collectList.get(0);
        }

        //如果没有 就获取 计划开始时间不为空的
        for (ImportErpWorkOrder orderInfo : infoList) {
            if (orderInfo.getPlanStartTime() != null) {
                return orderInfo;
            }
        }
        return null;
    }

    public Integer getSerialNum(String constructNo, Integer orderType) {
        List<Order> list = orderMapper.lambdaQuery()
                .eq(Order::getConstructNo, constructNo)
                .eq(Order::getOrderType, orderType)
                .list();

        if (CollUtil.isNotEmpty(list)) {
            if (list.get(0).getSerialNum() == null) {
                Order max = orderMapper.lambdaQuery().eq(Order::getOrderType, orderType).orderByDesc(Order::getSerialNum).last(" limit 1").one();
                int serialCode = 0;
                if (max != null && max.getSerialNum() != null) {
                    serialCode = max.getSerialNum();
                }

                return serialCode + 1;
            } else {
                return list.get(0).getSerialNum();
            }
        } else {
            Order max = orderMapper.lambdaQuery().eq(Order::getOrderType, orderType).orderByDesc(Order::getSerialNum).last(" limit 1").one();
            int serialCode = 0;
            if (max != null && max.getSerialNum() != null) {
                serialCode = max.getSerialNum();
            }
            return serialCode + 1;

        }
    }

    @Transactional
    public void orderErpAppend(ImportFrameOrderErpAppendReqVo reqVo) {
        ImportFrameOrder importFrameOrder = MkBeanUtils.copyProperties(reqVo, ImportFrameOrder.class, "id");
        importFrameOrderMapper.insert(importFrameOrder);

        ImportFrameOrderPubReqVo pubReqVo = new ImportFrameOrderPubReqVo();
        pubReqVo.setId(reqVo.getId());
        pubReqVo.setTargetId(importFrameOrder.getId());
        orderErp(pubReqVo);
    }

    @Transactional
    public void orderMbd(ImportFrameOrderMbdReqVo reqVo) {

        Order order = orderMapper.selectById(reqVo.getId());
        List<OrderBom> orderBomList = orderBomMapper.lambdaQuery().eq(OrderBom::getOrderId, reqVo.getId()).list();
        List<OrderPhase> orderPhaseList = orderPhaseMapper.lambdaQuery().eq(OrderPhase::getOrderId, reqVo.getId()).list();

        String[] ignoreProp = new String[]{"id", "createDateTime", "modifyDateTime", "deleted", "createUsername", "modifyUsername", "factoryId"};

        Order newOrder = MkBeanUtils.copyProperties(order, Order.class, ignoreProp);
        newOrder.setOrderType(5);
        newOrder.setOrderCode(reqVo.getConstructCode());
        newOrder.setConstructNo(reqVo.getConstructCode());

        Optional<OrderBom> first = orderBomList.stream().filter(e -> e.getPid() == null).findFirst();
        if (first.isPresent()) {
            OrderBom top = first.get();
            newOrder.setMaterName(top.getMaterName());
            newOrder.setMaterCode(top.getMaterCode());
            newOrder.setPlmId(top.getPlmId());
        }

        Order max = orderMapper.lambdaQuery()
                .in(Order::getOrderType, 2, 5)
                .ge(Order::getOrderStatus, 2)
                .eq(Order::getPlannedMonth, reqVo.getPlannedMonth())
                .isNotNull(Order::getSeq)
                .orderByDesc(Order::getSeq)
                .last("LIMIT 1")
                .one();

        newOrder.setOrderQty(1);
        newOrder.setFinishQty(0);
        newOrder.setOrderStatus(1);
        String suffix = OrderUtils.partType(newOrder.getPlmId(), newOrder.getMaterName());
        newOrder.setSuffix(suffix);
        newOrder.setPlannedMonth(reqVo.getPlannedMonth());
        newOrder.setSeq(max == null ? 1 : max.getSeq() + 1);
        orderMapper.insert(newOrder);

        Map<Integer, Integer> newBomIdMap = new HashMap<>();
        Map<Integer, List<OrderPhase>> phaseBomIdMap = orderPhaseList.stream().collect(Collectors.groupingBy(OrderPhase::getBomId));
        for (OrderBom bom : orderBomList) {

            OrderBom newBom = MkBeanUtils.copyProperties(bom, OrderBom.class, ignoreProp);
            newBom.setOrderId(newOrder.getId());
            if (bom.getPid() != null) {
                newBom.setPid(newBomIdMap.getOrDefault(bom.getPid(), null));
            }
            orderBomMapper.insert(newBom);

            newBomIdMap.put(bom.getId(), newBom.getId());

            List<OrderPhase> orderPhases = phaseBomIdMap.get(bom.getId());
            if (CollUtil.isEmpty(orderPhases)) {
                continue;
            }

            for (OrderPhase phase : orderPhases) {
                OrderPhase newPhase = MkBeanUtils.copyProperties(phase, OrderPhase.class, ignoreProp);
                newPhase.setBomId(newBom.getId());
                newPhase.setOrderId(newOrder.getId());
                orderPhaseMapper.insert(newPhase);
            }

        }

        try {
            NestRule nestRule = strategyConfig.getNestRule(NestRule.LANTEK_PRE);
            List<OrderBom> orderBomPushList = orderBomMapper.lambdaQuery().eq(OrderBom::getOrderId, newOrder.getId()).eq(OrderBom::getMaterType, "Platepart").list();
            nestRule.partAdd(orderBomPushList);
        } catch (Exception e) {
            log.info("零件图纸同步失败。");
        }


        // -------------
        Order one = orderMapper.lambdaQuery()
                .in(Order::getOrderType, 2, 5)
                .ge(Order::getOrderStatus, 2)
                .eq(Order::getConstructNo, reqVo.getConstructCode())
                .last(" limit 1 ")
                .one();

        if (one == null) {
            newOrder.setOrderStatus(2);
            orderMapper.updateById(newOrder);
            return;
        }

        if (!one.getPlannedMonth().equals(reqVo.getPlannedMonth())) {
            throw SyExceptionUtils.e("计划月份不一致,目标月份:{},当前月份:{}", one.getPlannedMonth(), reqVo.getPlannedMonth());
        }

        Integer minSeq = one.getSeq();

        List<Order> orderList = orderMapper.lambdaQuery()
                .eq(Order::getPlannedMonth, reqVo.getPlannedMonth())
                .in(Order::getOrderType, 2, 5)
                .ge(Order::getOrderStatus, 2)
                .ge(Order::getSeq, minSeq)
                .list();

        List<Order> eqOrder = orderList.stream().filter(e -> e.getConstructNo().equals(reqVo.getConstructCode())).collect(Collectors.toList());

        List<Order> neOrder = orderList.stream().filter(e -> !e.getConstructNo().equals(reqVo.getConstructCode())).collect(Collectors.toList());

        Map<String, Integer> orderTypes = new HashMap<>();
        orderTypes.put("D", 1);
        orderTypes.put("Z", 2);
        orderTypes.put("Y", 3);
        orderTypes.put("C", 4);
        orderTypes.put("L", 5);
        orderTypes.put("T", 6);
        orderTypes.put("B", 7);

        eqOrder.add(newOrder);
        eqOrder.sort(Comparator.comparing(e -> orderTypes.get(e.getSuffix())));

        neOrder.sort(Comparator.comparing(Order::getSeq));

        eqOrder.addAll(neOrder);
        newOrder.setOrderStatus(2);
        for (int i = 0; i < eqOrder.size(); i++) {
            Order ooo = eqOrder.get(i);
            ooo.setSeq(i + minSeq);
            orderMapper.updateById(ooo);
        }

    }

    @Transactional
    public void split(OrderSplitReqVo reqVo) {
        Order sourceOrder = orderMapper.selectById(reqVo.getOrderId());

        if (sourceOrder == null) {
            throw SyExceptionUtils.e("订单不存在");
        }

        reqVo.setSourceLineId(sourceOrder.getLineId());

        if (reqVo.getSourceLineId().equals(reqVo.getTargetLineId()) && reqVo.getSourceCount().equals(reqVo.getTargetCount())) {
            return ;
        }

        if(reqVo.getTargetCount() == null){
            return ;
        }
        if(reqVo.getSourceCount() < 0 || reqVo.getTargetCount() < 0){
            throw SyExceptionUtils.e("数量不能小于0");
        }


        if(sourceOrder.getOrderQty() != (reqVo.getSourceCount() + reqVo.getTargetCount())){
            throw SyExceptionUtils.e("拆分后的数量之和必须和订单原数量保持一致");
        }

        if(sourceOrder.getOrderStatus() >= 3){
            throw SyExceptionUtils.e("订单已开始生产");
        }

        // 源数据
        List<OrderBom> sourceBomList = orderBomMapper.lambdaQuery().eq(OrderBom::getOrderId, reqVo.getOrderId()).list();
        List<OrderPhase> sourcePhaseList = orderPhaseMapper.lambdaQuery().eq(OrderPhase::getOrderId, reqVo.getOrderId()).list();
        List<OrderAccessories> sourceOaList = orderAccessoriesMapper.lambdaQuery().eq(OrderAccessories::getOrderId, reqVo.getOrderId()).list();

        // 转换Order
        Order targetOrder = new Order();
        MkBeanUtils.copyPropertiesIgnore(sourceOrder, targetOrder);
        String oriConsNo = null;
        if (targetOrder.getConstructNo().matches(".+-\\d{1}$")) {
            oriConsNo = targetOrder.getConstructNo().substring(0, targetOrder.getConstructNo().length() - 2);
        } else {
            oriConsNo = targetOrder.getConstructNo();
        }
        Order maxOrder = orderMapper.lambdaQuery().in(Order::getOrderType, 1,3,4,6)
                .eq(Order::getConstructNo, targetOrder.getConstructNo())
                .eq(Order::getMaterCode, sourceOrder.getMaterCode())
                .isNotNull(Order::getSplitCode)
                .orderByDesc(Order::getConstructNo)
                .last("limit 1")
                .one();
        int maxNum = 1;
        if(maxOrder != null){
            maxNum = Integer.parseInt(maxOrder.getConstructNo().substring(maxOrder.getConstructNo().length() - 1)) + 1;
        }

        targetOrder.setConstructNo(oriConsNo);
        targetOrder.setSplitCode(oriConsNo + "-" + maxNum);
        targetOrder.setOrderQty(reqVo.getTargetCount());
        targetOrder.setLineId(reqVo.getTargetLineId());
//        targetOrder.setLineId(reqVo.getTargetLineId());
        orderMapper.insert(targetOrder);

        sourceOrder.setOrderQty(reqVo.getSourceCount());
        orderMapper.updateById(sourceOrder);

        // 转换BOM
        Map<Integer, Integer> bomMappingMap = new HashMap<>();
        sourceBomList.sort(Comparator.comparing(OrderBom::getLevel));
        for (OrderBom sourceBom : sourceBomList) {
            OrderBom targetBom = new OrderBom();
            MkBeanUtils.copyPropertiesIgnore(sourceBom, targetBom);
            targetBom.setOrderId(targetOrder.getId());
            targetBom.setPid(bomMappingMap.get(sourceBom.getPid()));
            orderBomMapper.insert(targetBom);

            bomMappingMap.put(sourceBom.getId(), targetBom.getId());
        }

        // 转换工序
        List<Group> targetGroupList = groupMapper.lambdaQuery().eq(Group::getLineId, targetOrder.getLineId()).eq(Group::getType, 2).isNotNull(Group::getMyCode).list();
        Map<String, Group> groupMap = targetGroupList.stream().collect(Collectors.toMap(Group::getMyCode, e -> e));

        Map<Integer, Integer> phaseMappingMap = new HashMap<>();
        for (OrderPhase sourcePhase : sourcePhaseList) {
            OrderPhase targetPhase = new OrderPhase();
            MkBeanUtils.copyPropertiesIgnore(sourcePhase, targetPhase);
            targetPhase.setOrderId(targetOrder.getId());
            targetPhase.setBomId(bomMappingMap.get(sourcePhase.getBomId()));
            Group group = groupMap.get(targetPhase.getWorkGroupNumber());
            if(group == null){
                throw SyExceptionUtils.e("目标产线缺少工作组：{}", targetPhase.getWorkGroupNumber());
            }
            orderPhaseMapper.insert(targetPhase);
            phaseMappingMap.put(sourcePhase.getId(), targetPhase.getId());
        }

        // 转换辅料
        for (OrderAccessories sourceOa : sourceOaList) {
            OrderAccessories targetOa = new OrderAccessories();
            MkBeanUtils.copyPropertiesIgnore(sourceOa, targetOa);
            targetOa.setOrderId(targetOrder.getId());
            targetOa.setPhaseId(phaseMappingMap.get(sourceOa.getPhaseId()));
            targetOa.setBomId(bomMappingMap.get(sourceOa.getBomId()));
            orderAccessoriesMapper.insert(targetOa);
        }

        if(reqVo.getSourceCount() <= 0){
            orderMapper.deleteReal(sourceOrder.getId());
            orderBomMapper.deleteReal(sourceOrder.getId());
            orderPhaseMapper.deleteReal(sourceOrder.getId());
            orderAccessoriesMapper.deleteReal(sourceOrder.getId());
        }

    }

    @Transactional
    public void importExcel(Integer orderId, File file) {

        List<OrderExcelReqVo> list = FastExcel.read(file, OrderExcelReqVo.class, new DemoDataListener()).sheet().doReadSync();

        Integer count = orderBomMapper.lambdaQuery().eq(OrderBom::getOrderId, orderId).count();
        if(count > 0){
            throw SyExceptionUtils.e("该订单已有BOM");
        }

        Order order = orderMapper.selectById(orderId);
        if (order.getOrderStatus() > 1) {
            throw SyExceptionUtils.e("订单状态不一致!");
        }

        if(order.getLineId() == null){
            throw SyExceptionUtils.e("没有选产线，无法自动匹配工序和工作组");
        }

        /**
         * 系统在执行Excel表的解析时，需做相应的数据校验。
         * A、零件类型的物料必须包含材质、板厚；
         * B、物料的工序、工作中心均需在系统中定义；
         * C、导入的Excel表的订单号需与创建的订单号保持一致；
         * D、导入的Excel表的产品编号需与创建的订单产品号保持一致；
         * 如检验不通过，需做异常提醒，异常提醒内容需根据后续功能使用情况逐步完善。
         * 在数据解析、上传时，系统需根据父物料图号信息构建起BOM结构，无父物料图号的物料为顶级物料，一个Excel仅允许存在一个顶级物料。
         */

        List<OrderExcelReqVo> topList = list.stream().filter(e -> e.getParentCode().equals("/")).collect(Collectors.toList());
        if(topList.size() > 1){
            throw SyExceptionUtils.e("只能有一个顶级！");
        }
        for (OrderExcelReqVo top : topList) {
            if(!top.getConstructNo().equals(order.getConstructNo()) || !top.getMaterCode().equals(order.getMaterCode())){
                throw SyExceptionUtils.e("施工号或部件号不匹配");
            }
        }

        // 工序和工作重心在系统中有定义
        List<PhaseGroup> phaseGroupList = phaseGroupMapper.lambdaQuery().isNotNull(PhaseGroup::getGroupCode).isNotNull(PhaseGroup::getPhaseCode).list();
        Map<String, List<PhaseGroup>> phaseGroupMap1 = phaseGroupList.stream().collect(Collectors.groupingBy(PhaseGroup::getPhaseCode));
        Map<String, Phase> phaseMap = phaseMapper.lambdaQuery().list().stream().collect(Collectors.toMap(Phase::getMyCode, Function.identity()));
        List<Group> groupList = groupMapper.lambdaQuery().eq(Group::getType, 2).eq(Group::getLineId, order.getLineId()).isNotNull(Group::getMyCode).list();
        Map<String, Group> groupMap = groupList.stream().collect(Collectors.toMap(Group::getMyCode, e -> e));
        list.forEach(e -> {
            Phase phaseOne = phaseMap.get(e.getPhaseOne());
            if (ObjectUtils.isEmpty(phaseOne)) {
                // 信息记录，输出 Excel
                throw SyExceptionUtils.e(e.getPhaseOne() + "工序不存在");
            }
            if(!StringUtils.hasText(e.getCenterOne())){
                List<PhaseGroup> phaseGroups = phaseGroupMap1.get(e.getPhaseOne());
                if(CollUtil.isNotEmpty(phaseGroups)){
                    e.setCenterOne(phaseGroups.get(0).getGroupCode());
                }
            }
            Group groupOne = groupMap.get(e.getCenterOne());
            if (ObjectUtils.isEmpty(groupOne)) {
                // 信息
                throw SyExceptionUtils.e(e.getCenterOne() + "工作组不存在");
            }

            Phase phaseTwo = phaseMap.get(e.getPhaseTwo());
            if (ObjectUtils.isEmpty(phaseTwo)) {
                // 信息记录，输出 Excel
                throw SyExceptionUtils.e(e.getPhaseTwo() + "工序不存在");
            }
            if(!StringUtils.hasText(e.getCenterTwo())){
                List<PhaseGroup> phaseGroups = phaseGroupMap1.get(e.getPhaseTwo());
                if(CollUtil.isNotEmpty(phaseGroups)){
                    e.setCenterTwo(phaseGroups.get(0).getGroupCode());
                }
            }
            Group groupTwo = groupMap.get(e.getCenterTwo());
            if (ObjectUtils.isEmpty(groupTwo)) {
                // 信息
                throw SyExceptionUtils.e(e.getCenterTwo() + "工作组不存在");
            }
            Phase phaseThree = phaseMap.get(e.getPhaseThree());
            if (ObjectUtils.isEmpty(phaseThree)) {
                // 信息记录，输出 Excel
                throw SyExceptionUtils.e(e.getPhaseThree() + "工序不存在");
            }
            if(!StringUtils.hasText(e.getCenterThree())){
                List<PhaseGroup> phaseGroups = phaseGroupMap1.get(e.getPhaseThree());
                if(CollUtil.isNotEmpty(phaseGroups)){
                    e.setCenterThree(phaseGroups.get(0).getGroupCode());
                }
            }
            Group groupThree = groupMap.get(e.getCenterThree());
            if (ObjectUtils.isEmpty(groupThree)) {
                // 信息
                throw SyExceptionUtils.e(e.getCenterThree() + "工作组不存在");
            }
            Phase phaseFour = phaseMap.get(e.getPhaseFour());
            if (ObjectUtils.isEmpty(phaseFour)) {
                // 信息记录，输出 Excel
                throw SyExceptionUtils.e(e.getPhaseFour() + "工序不存在");
            }
            if(!StringUtils.hasText(e.getCenterFour())){
                List<PhaseGroup> phaseGroups = phaseGroupMap1.get(e.getPhaseFour());
                if(CollUtil.isNotEmpty(phaseGroups)){
                    e.setCenterFour(phaseGroups.get(0).getGroupCode());
                }
            }
            Group groupFour = groupMap.get(e.getCenterFour());
            if (ObjectUtils.isEmpty(groupFour)) {
                // 信息
                throw SyExceptionUtils.e(e.getCenterFour() + "工作组不存在");
            }
        });


        Map<String, String> typeMap = new HashMap<>();
        typeMap.put("零件", "Platepart");
        typeMap.put("组件", "Assembly");

        List<OrderExcelReqVo> voList = list.stream().filter(e -> e.getParentCode().equals("/")).collect(Collectors.toList());
        OrderExcelReqVo vo = voList.get(0);

        order.setMaterName(vo.getMaterName());
        order.setOrderStatus(1);
        order.setLocked(1);
        order.setFactoryCode("170");
        order.setFinishQty(0);
        order.setPushStatus(1);
//        order.setCustomerCode("1");
//        order.setCustomerId(3);
//        order.setCustomerName("传动");
        orderMapper.updateById(order);

//        List<Group> groupList = groupMapper.lambdaQuery()
//                .eq(order.getLineId() != null, Group::getLineId, order.getLineId())
//                .list();
        Map<String, List<PhaseGroup>> phaseGroupMap = phaseGroupMapper.lambdaQuery()
                .in(CollUtil.isNotEmpty(groupList), PhaseGroup::getGroupCode, groupList.stream().map(Group::getMyCode).collect(Collectors.toList()))
                .list()
                .stream()
                .collect(Collectors.groupingBy(PhaseGroup::getPhaseCode));

        List<OrderBom> parBomList = new ArrayList<>();
        int level = 1;
        Map<String, List<OrderExcelReqVo>> voMap = list.stream().collect(Collectors.groupingBy(OrderExcelReqVo::getParentCode));

        String path = "";

        List<OrderExcelReqVo> topVoList = voMap.get("/");
        OrderExcelReqVo topVo = topVoList.get(0);
        OrderBom topBom = new OrderBom();
        topBom.setTopFlag(1);
        topBom.setFactoryNo("170");
        topBom.setMaterCode(topVo.getMaterCode());
        topBom.setPlmId(topVo.getMaterCode());
        topBom.setMaterName(topVo.getMaterName());
        topBom.setMaterType(typeMap.get(topVo.getMaterType()));
        topBom.setLevel(level);
        topBom.setTotalCount(topVo.getTotalCount());
        topBom.setPartCount(topVo.getTotalCount());
        topBom.setStandards(topVo.getTexture() + "δ" + topVo.getThickness());
        topBom.setWorkChain(topVo.getPhaseOne() + "-" + topVo.getPhaseTwo() + "-" + topVo.getPhaseThree() + "-" + topVo.getPhaseFour());
        topBom.setOrderId(order.getId());
        path = "/" + topBom.getMaterCode();
        topBom.setAssemblyPath(path);
        topBom.setReadyType(1);
        orderBomMapper.insert(topBom);
        creatBomPhase(topBom, topVo, phaseGroupMap);
        parBomList.add(topBom);

        while (true) {
            List<OrderBom> childBomList = new ArrayList<>();
            level++;
            for (OrderBom bom : parBomList) {
                List<OrderExcelReqVo> childList = voMap.get(bom.getMaterCode());
                if (CollUtil.isNotEmpty(childList)) {
                    for (OrderExcelReqVo childVo : childList) {
                        String pathChild = bom.getAssemblyPath() + "/" + childVo.getMaterCode();
                        OrderBom childBom = new OrderBom();
                        childBom.setTopFlag(0);
                        childBom.setFactoryNo("170");
                        childBom.setMaterCode(childVo.getMaterCode());
                        childBom.setPlmId(childVo.getMaterCode());
                        childBom.setMaterName(childVo.getMaterName());
                        childBom.setMaterType(typeMap.get(childVo.getMaterType()));
                        childBom.setLevel(level);
                        childBom.setTotalCount(childVo.getTotalCount());
                        childBom.setPartCount(childVo.getTotalCount());
                        childBom.setStandards(childVo.getTexture() + "δ" + childVo.getThickness());
                        childBom.setWorkChain(childVo.getPhaseOne() + "-" + childVo.getPhaseTwo() + "-" + childVo.getPhaseThree() + "-" + childVo.getPhaseFour());
                        childBom.setPid(bom.getId());
                        childBom.setOrderId(order.getId());
                        childBom.setAssemblyPath(pathChild);
                        childBom.setReadyType(1);
                        orderBomMapper.insert(childBom);
                        creatBomPhase(childBom, childVo, phaseGroupMap);
                        childBomList.add(childBom);
                    }
                }
            }
            if (CollUtil.isEmpty(childBomList)) {
                break;
            }
            parBomList = childBomList;
        }


    }

    public void createOrderC(List<OrderExcelReqVo> list) {

        Map<String, String> typeMap = new HashMap<>();
        typeMap.put("零件", "Platepart");
        typeMap.put("组件", "Assembly");

        List<OrderExcelReqVo> voList = list.stream().filter(e -> e.getParentCode().equals("/")).collect(Collectors.toList());
        OrderExcelReqVo vo = voList.get(0);

        Order order = new Order();
        order.setConstructNo(vo.getConstructNo());
        order.setOrderCode(vo.getOrderCode());
        order.setMaterCode(vo.getMaterCode());
        order.setMaterName(vo.getMaterName());
        order.setOrderStatus(2);
        order.setPushType(1);
        order.setOrderType(1);
        order.setLocked(1);
        order.setFactoryCode("170");
        order.setFinishQty(0);
        order.setOrderDateTime(LocalDateTime.now());
        order.setOrderQty(vo.getTotalCount().intValue());
        order.setPushStatus(1);
        order.setCustomerCode("1");
        order.setCustomerId(3);
        order.setCustomerName("传动");
        order.setDeliveryDateTime(LocalDateTime.now().plusMonths(1));
        order.setLineId(2);
        orderMapper.insert(order);

        List<Group> groupList = groupMapper.lambdaQuery()
                .eq(order.getLineId() != null, Group::getLineId, order.getLineId())
                .list();
        Map<String, List<PhaseGroup>> phaseGroupMap = phaseGroupMapper.lambdaQuery()
                .in(CollUtil.isNotEmpty(groupList), PhaseGroup::getGroupCode, groupList.stream().map(Group::getMyCode).collect(Collectors.toList()))
                .list()
                .stream()
                .collect(Collectors.groupingBy(PhaseGroup::getPhaseCode));

        List<OrderBom> parBomList = new ArrayList<>();
        int level = 1;
        Map<String, List<OrderExcelReqVo>> voMap = list.stream().collect(Collectors.groupingBy(OrderExcelReqVo::getParentCode));

        String path = "";

        List<OrderExcelReqVo> topVoList = voMap.get("/");
        OrderExcelReqVo topVo = topVoList.get(0);
        OrderBom topBom = new OrderBom();
        topBom.setTopFlag(1);
        topBom.setFactoryNo("170");
        topBom.setMaterCode(topVo.getMaterCode());
        topBom.setPlmId(topVo.getMaterCode());
        topBom.setMaterName(topVo.getMaterName());
        topBom.setMaterType(typeMap.get(topVo.getMaterType()));
        topBom.setLevel(level);
        topBom.setTotalCount(topVo.getTotalCount());
        topBom.setPartCount(topVo.getTotalCount());
        topBom.setStandards(topVo.getTexture() + "δ" + topVo.getThickness());
        topBom.setWorkChain(topVo.getPhaseOne() + "-" + topVo.getPhaseTwo() + "-" + topVo.getPhaseThree() + "-" + topVo.getPhaseFour());
        topBom.setOrderId(order.getId());
        path = "/" + topBom.getMaterCode();
        topBom.setAssemblyPath(path);
        topBom.setReadyType(1);
        orderBomMapper.insert(topBom);
        creatBomPhase(topBom, topVo, phaseGroupMap);
        parBomList.add(topBom);

        while (true) {
            List<OrderBom> childBomList = new ArrayList<>();
            level++;
            for (OrderBom bom : parBomList) {
                List<OrderExcelReqVo> childList = voMap.get(bom.getMaterCode());
                if (CollUtil.isNotEmpty(childList)) {
                    for (OrderExcelReqVo childVo : childList) {
                        String pathChild = bom.getAssemblyPath() + "/" + childVo.getMaterCode();
                        OrderBom childBom = new OrderBom();
                        childBom.setTopFlag(0);
                        childBom.setFactoryNo("170");
                        childBom.setMaterCode(childVo.getMaterCode());
                        childBom.setPlmId(childVo.getMaterCode());
                        childBom.setMaterName(childVo.getMaterName());
                        childBom.setMaterType(typeMap.get(childVo.getMaterType()));
                        childBom.setLevel(level);
                        childBom.setTotalCount(childVo.getTotalCount());
                        childBom.setPartCount(childVo.getTotalCount());
                        childBom.setStandards(childVo.getTexture() + "δ" + childVo.getThickness());
                        childBom.setWorkChain(childVo.getPhaseOne() + "-" + childVo.getPhaseTwo() + "-" + childVo.getPhaseThree() + "-" + childVo.getPhaseFour());
                        childBom.setPid(bom.getId());
                        childBom.setOrderId(order.getId());
                        childBom.setAssemblyPath(pathChild);
                        childBom.setReadyType(1);
                        orderBomMapper.insert(childBom);
                        creatBomPhase(childBom, childVo, phaseGroupMap);
                        childBomList.add(childBom);
                    }
                }
            }
            if (CollUtil.isEmpty(childBomList)) {
                break;
            }
            parBomList = childBomList;
        }

    }

    public class DemoDataListener implements ReadListener<OrderExcelReqVo> {

        @Override
        public void invoke(OrderExcelReqVo data, AnalysisContext context) {
//            ((ReadCellData)context.readRowHolder().getCellMap().get(4)).getStringValue();

//            if(context.readRowHolder().getCellMap().get(99) != null){
//                data.setMaterName(((ReadCellData<?>)context.readRowHolder().getCellMap().get(4)).getStringValue());
//            }
//            ((ReadCellData)context.readRowHolder().getCellMap().get(4)).getStringValue();


            data.setConstructNo(((ReadCellData)context.readRowHolder().getCellMap().get(0)).getStringValue());
            data.setOrderCode(((ReadCellData)context.readRowHolder().getCellMap().get(1)).getStringValue());
            data.setParentCode(((ReadCellData)context.readRowHolder().getCellMap().get(2)).getStringValue());
            data.setMaterCode(((ReadCellData)context.readRowHolder().getCellMap().get(3)).getStringValue());
            data.setMaterName(((ReadCellData) context.readRowHolder().getCellMap().get(4)).getStringValue());
            data.setMaterType(((ReadCellData) context.readRowHolder().getCellMap().get(5)).getStringValue());
            data.setTotalCount(((ReadCellData) context.readRowHolder().getCellMap().get(6)).getOriginalNumberValue());
//            data.setDeliveryTime(((ReadCellData) context.readRowHolder().getCellMap().get(7)).getStringValue());
            data.setTexture(((ReadCellData) context.readRowHolder().getCellMap().get(8)).getStringValue() != null?((ReadCellData) context.readRowHolder().getCellMap().get(8)).getStringValue():((ReadCellData) context.readRowHolder().getCellMap().get(8)).getNumberValue().toString());
            data.setThickness(((ReadCellData) context.readRowHolder().getCellMap().get(9)).getStringValue());
            data.setNorm(((ReadCellData) context.readRowHolder().getCellMap().get(10)).getStringValue());
            data.setWeight(((ReadCellData) context.readRowHolder().getCellMap().get(11)).getNumberValue());
            data.setPhaseOne(((ReadCellData) context.readRowHolder().getCellMap().get(12)).getStringValue());
            data.setCenterOne(((ReadCellData) context.readRowHolder().getCellMap().get(13)).getStringValue());
            data.setWorkTimeOne(((ReadCellData) context.readRowHolder().getCellMap().get(14)).getNumberValue());
            data.setPhaseTwo(((ReadCellData) context.readRowHolder().getCellMap().get(15)).getStringValue());
            data.setCenterTwo(((ReadCellData) context.readRowHolder().getCellMap().get(16)).getStringValue());
            data.setWorkTimeTwo(((ReadCellData) context.readRowHolder().getCellMap().get(17)).getNumberValue());
            data.setPhaseThree(((ReadCellData) context.readRowHolder().getCellMap().get(18)).getStringValue());
            data.setCenterThree(((ReadCellData) context.readRowHolder().getCellMap().get(19)).getStringValue());
            data.setWorkTimeThree(((ReadCellData) context.readRowHolder().getCellMap().get(20)).getNumberValue());
            data.setPhaseFour(((ReadCellData) context.readRowHolder().getCellMap().get(21)).getStringValue());
            data.setCenterFour(((ReadCellData) context.readRowHolder().getCellMap().get(22)).getStringValue());
            data.setWorkTimeFour(((ReadCellData) context.readRowHolder().getCellMap().get(23)).getNumberValue());

            System.out.println("解析到一条数据" + JsonUtils.toJsonString(data));

        }

        @Override
        public void doAfterAllAnalysed(AnalysisContext context) {
            System.out.println("所有数据解析完成！");
        }
    }

    public void creatBomPhase(OrderBom bom, OrderExcelReqVo vo, Map<String, List<PhaseGroup>> map) {
        List<OrderPhase> orderPhseList = new ArrayList<>();

        OrderPhase orderPhaseOne = new OrderPhase();
        orderPhaseOne.setBomId(bom.getId());
        orderPhaseOne.setMaterName(bom.getMaterName());
        orderPhaseOne.setMaterNo(bom.getMaterCode());
        orderPhaseOne.setOrderId(bom.getOrderId());
        orderPhaseOne.setPhaseCode(vo.getPhaseOne());
        orderPhaseOne.setPhaseName(vo.getPhaseOne());
        orderPhaseOne.setPhaseSeq(1);
        orderPhaseOne.setWorkChain(bom.getWorkChain());
        orderPhaseOne.setWorkTime(vo.getWorkTimeOne().intValue());
        orderPhaseOne.setOriWorkTime(vo.getWorkTimeOne().intValue());
        orderPhaseOne.setWorkGroupNumber(vo.getCenterOne());
        orderPhseList.add(orderPhaseOne);

        OrderPhase orderPhaseTwo = new OrderPhase();
        orderPhaseTwo.setBomId(bom.getId());
        orderPhaseTwo.setMaterName(bom.getMaterName());
        orderPhaseTwo.setMaterNo(bom.getMaterCode());
        orderPhaseTwo.setOrderId(bom.getOrderId());
        orderPhaseTwo.setPhaseCode(vo.getPhaseTwo());
        orderPhaseTwo.setPhaseName(vo.getPhaseTwo());
        orderPhaseTwo.setPhaseSeq(2);
        orderPhaseTwo.setWorkChain(bom.getWorkChain());
        orderPhaseTwo.setWorkTime(vo.getWorkTimeTwo().intValue());
        orderPhaseTwo.setOriWorkTime(vo.getWorkTimeTwo().intValue());
        orderPhaseTwo.setWorkGroupNumber(vo.getCenterTwo());
        orderPhseList.add(orderPhaseTwo);

        OrderPhase orderPhaseThree = new OrderPhase();
        orderPhaseThree.setBomId(bom.getId());
        orderPhaseThree.setMaterName(bom.getMaterName());
        orderPhaseThree.setMaterNo(bom.getMaterCode());
        orderPhaseThree.setOrderId(bom.getOrderId());
        orderPhaseThree.setPhaseCode(vo.getPhaseThree());
        orderPhaseThree.setPhaseName(vo.getPhaseThree());
        orderPhaseThree.setPhaseSeq(3);
        orderPhaseThree.setWorkChain(bom.getWorkChain());
        orderPhaseThree.setWorkTime(vo.getWorkTimeThree().intValue());
        orderPhaseThree.setOriWorkTime(vo.getWorkTimeThree().intValue());
        orderPhaseThree.setWorkGroupNumber(vo.getCenterThree());
        orderPhseList.add(orderPhaseThree);

        OrderPhase orderPhaseFour = new OrderPhase();
        orderPhaseFour.setBomId(bom.getId());
        orderPhaseFour.setMaterName(bom.getMaterName());
        orderPhaseFour.setMaterNo(bom.getMaterCode());
        orderPhaseFour.setOrderId(bom.getOrderId());
        orderPhaseFour.setPhaseCode(vo.getPhaseFour());
        orderPhaseFour.setPhaseName(vo.getPhaseFour());
        orderPhaseFour.setPhaseSeq(4);
        orderPhaseFour.setWorkChain(bom.getWorkChain());
        orderPhaseFour.setWorkTime(vo.getWorkTimeFour().intValue());
        orderPhaseFour.setOriWorkTime(vo.getWorkTimeFour().intValue());
        orderPhaseFour.setWorkGroupNumber(vo.getCenterFour());
        orderPhseList.add(orderPhaseFour);

        orderPhaseMapper.insertBatchSomeColumn(orderPhseList);

    }

    @Transactional
    public void addOrderNew(OrderAddNewReqVo reqVo) {
        Order order = new Order();
        order.setOrderCode(reqVo.getOrderCode());
        order.setConstructNo(reqVo.getOrderCode());
        order.setDeliveryDateTime(reqVo.getDeliveryDate());
        order.setMaterCode(reqVo.getMaterCode());
        order.setMaterName(reqVo.getMaterName());
        order.setOrderQty(reqVo.getOrderQty());
        order.setOrderType(reqVo.getOrderType() != null ? reqVo.getOrderType() : 6);
        order.setCustomerId(reqVo.getCustomerId());
        order.setOrderPriority(reqVo.getOrderPriority());
        order.setOrderStatus(1);
        order.setLineId(reqVo.getLineId());

        if (Objects.nonNull(order.getCustomerId())) {
            Customer customer = customerMapper.selectById(reqVo.getCustomerId());
            if(customer == null){
                throw SyExceptionUtils.e("没有找到该客户");
            }
            order.setCustomerCode(customer.getMyCode());
            order.setCustomerName(customer.getName());
        }
//        order.setSplitCode("/");

        order.setFactoryCode("170");
        order.setOrderDateTime(LocalDateTime.now());
        List<Order> list = orderMapper.lambdaQuery().eq(Order::getConstructNo, order.getConstructNo()).in(Order::getOrderType, 1, 3, 4).list();
        if (CollUtil.isNotEmpty(list)) {
            if (list.get(0).getSerialNum() == null) {
                Order max = orderMapper.lambdaQuery().orderByDesc(Order::getSerialNum).last(" limit 1").one();
                int serialCode = 0;
                if (max != null && max.getSerialNum() != null) {
                    serialCode = max.getSerialNum();
                }
                order.setSerialNum(serialCode + 1);
                order.setSerialCode(String.format("%04d-", order.getSerialNum()) + order.getConstructNo());
            } else {
                order.setSerialNum(list.get(0).getSerialNum());
                order.setSerialCode(list.get(0).getSerialCode());
            }
        } else {
            Order max = orderMapper.lambdaQuery().orderByDesc(Order::getSerialNum).last(" limit 1").one();
            int serialCode = 0;
            if (max != null && max.getSerialNum() != null) {
                serialCode = max.getSerialNum();
            }
            order.setSerialNum(serialCode + 1);
            order.setSerialCode(String.format("%04d-", order.getSerialNum()) + order.getConstructNo());
        }

        orderMapper.insert(order);

    }

    @Transactional
    public void editOrderNew(OrderEditNewReqVo reqVo) {
        Order order = orderMapper.selectById(reqVo.getId());
        BeanUtils.copyProperties(reqVo, order);
        if (Objects.nonNull(order.getCustomerId())) {
            Customer customer = customerMapper.selectById(reqVo.getCustomerId());
            if(customer == null){
                throw SyExceptionUtils.e("没有找到该客户");
            }
            order.setCustomerCode(customer.getMyCode());
            order.setCustomerName(customer.getName());
        }

        orderMapper.updateById(order);
    }

}
